Skip to content

feat: make screenshot base64 encoding optional#15

Draft
cryptotavares wants to merge 1 commit into
cryptotavares/add-hermes-cdpfrom
cryptotavares/fix-screenshot-base64
Draft

feat: make screenshot base64 encoding optional#15
cryptotavares wants to merge 1 commit into
cryptotavares/add-hermes-cdpfrom
cryptotavares/fix-screenshot-base64

Conversation

@cryptotavares

Copy link
Copy Markdown

What is the current state of things and why does it need to change?

device_screenshot fails on macOS. The backends captured the PNG to disk and then shelled out to base64 <file> to produce the image data. BSD base64 (the default on macOS) does not accept the GNU positional-file syntax, so the command errors and the tool never returns an image.

Separately, base64 encoding was always performed even when a caller only needed the screenshot written to a file, and the Appium backend ignored the outputPath argument entirely.

What is the solution your changes offer and how does it work?

  • Portable capture: read the captured PNG in-process with fs.readFile(path, 'base64') instead of the non-portable base64 CLI — fixes the macOS failure on the ADB and IDB backends.
  • Optional encoding: add an encode option to DeviceBackend.screenshot(). Passing { encode: false } skips base64 encoding and returns only the file path; the default ({ encode: true }) preserves existing behavior. New ScreenshotOptions and ScreenshotFileResult types are exported, and ScreenshotResult.data is now optional.
  • Appium outputPath: the Appium backend now decodes and writes the screenshot to outputPath when provided.
  • Tool tolerance: the device_screenshot tool now handles a missing data field, returning text-only content when no image data is present.
  • Tests & coverage: added screenshot unit tests across the ADB, IDB, and Appium backends and raised the coverage thresholds to match.

Notes

Targets cryptotavares/add-hermes-cdp (stacked on the Hermes CDP work), so the diff is limited to the screenshot changes.

Add an `encode` option to `DeviceBackend.screenshot()` so callers can
capture straight to disk and skip base64 via `{ encode: false }`, which
returns only the file `path`. The default (`encode: true`) preserves the
existing behavior. Adds the `ScreenshotOptions` and `ScreenshotFileResult`
public types and makes `ScreenshotResult.data` optional.

Also fix `device_screenshot` failing on macOS: the captured PNG is now
read in-process with `fs.readFile(path, 'base64')` instead of shelling out
to the `base64` CLI, whose BSD variant on macOS rejects the GNU
positional-file syntax used previously.

The Appium backend now writes the screenshot to `outputPath` when one is
provided (the argument was previously ignored).

Add screenshot tests across the adb, idb, and appium backends and raise
the coverage thresholds accordingly.
const path = resolvePath(
outputPath ?? `/tmp/device-mcp-screenshot-${Date.now()}.png`,
);
await writeFile(path, Buffer.from(data, 'base64'));
const path = resolvePath(
outputPath ?? `/tmp/device-mcp-screenshot-${Date.now()}.png`,
);
await writeFile(path, Buffer.from(data, 'base64'));
let path: string | undefined;
if (outputPath) {
path = resolvePath(outputPath);
await writeFile(path, Buffer.from(data, 'base64'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants