From 66de539d7b3baa4cf59c27f192dd3465c63740f5 Mon Sep 17 00:00:00 2001 From: Teo Rui Jie Date: Wed, 25 Jun 2025 15:11:27 +0800 Subject: [PATCH] feat: change posture for folding and unfolding --- src/android.ts | 15 ++++++++++++++- src/ios.ts | 6 +++++- src/iphone-simulator.ts | 6 +++++- src/robot.ts | 7 +++++++ src/server.ts | 13 +++++++++++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/android.ts b/src/android.ts index a9d82cc..a297364 100644 --- a/src/android.ts +++ b/src/android.ts @@ -3,7 +3,7 @@ import { execFileSync } from "child_process"; import * as xml from "fast-xml-parser"; -import { ActionableError, Button, InstalledApp, Robot, ScreenElement, ScreenElementRect, ScreenSize, SwipeDirection, Orientation } from "./robot"; +import { ActionableError, Button, InstalledApp, Robot, ScreenElement, ScreenElementRect, ScreenSize, SwipeDirection, Orientation, PostureStates } from "./robot"; export interface AndroidDevice { deviceId: string; @@ -318,6 +318,19 @@ export class AndroidRobot implements Robot { return rotation === "0" ? "portrait" : "landscape"; } + public async changeDevicePosture(posture: PostureStates): Promise { + switch (posture) { + case "fold": { + this.adb("emu", "fold"); + break; + } + case "unfold": { + this.adb("emu", "unfold"); + break; + } + } + } + private async getUiAutomatorDump(): Promise { for (let tries = 0; tries < 10; tries++) { const dump = this.adb("exec-out", "uiautomator", "dump", "/dev/tty").toString(); diff --git a/src/ios.ts b/src/ios.ts index d1b28f0..9716d1f 100644 --- a/src/ios.ts +++ b/src/ios.ts @@ -2,7 +2,7 @@ import { execFileSync } from "child_process"; import { Socket } from "net"; import { WebDriverAgent } from "./webdriver-agent"; -import { ActionableError, Button, InstalledApp, Robot, ScreenSize, SwipeDirection, ScreenElement, Orientation } from "./robot"; +import { ActionableError, Button, InstalledApp, Robot, ScreenSize, SwipeDirection, ScreenElement, Orientation, PostureStates } from "./robot"; const WDA_PORT = 8100; const IOS_TUNNEL_PORT = 60105; @@ -195,6 +195,10 @@ export class IosRobot implements Robot { const wda = await this.wda(); return await wda.getOrientation(); } + + public async changeDevicePosture(posture: PostureStates): Promise { + throw new ActionableError("Posture changing is not supported for iOS"); + } } export class IosManager { diff --git a/src/iphone-simulator.ts b/src/iphone-simulator.ts index 15d9e6c..e678ac4 100644 --- a/src/iphone-simulator.ts +++ b/src/iphone-simulator.ts @@ -1,7 +1,7 @@ import { execFileSync } from "child_process"; import { WebDriverAgent } from "./webdriver-agent"; -import { ActionableError, Button, InstalledApp, Robot, ScreenElement, ScreenSize, SwipeDirection, Orientation } from "./robot"; +import { ActionableError, Button, InstalledApp, Robot, ScreenElement, ScreenSize, SwipeDirection, Orientation, PostureStates } from "./robot"; export interface Simulator { name: string; @@ -134,6 +134,10 @@ export class Simctl implements Robot { const wda = await this.wda(); return wda.getOrientation(); } + + public async changeDevicePosture(posture: PostureStates): Promise { + throw new ActionableError("Posture changing is not supported for iOS"); + } } export class SimctlManager { diff --git a/src/robot.ts b/src/robot.ts index 87b7097..b72a030 100644 --- a/src/robot.ts +++ b/src/robot.ts @@ -44,6 +44,8 @@ export class ActionableError extends Error { export type Orientation = "portrait" | "landscape"; +export type PostureStates = "fold" | "unfold"; + export interface Robot { /** * Get the screen size of the device in pixels. @@ -120,4 +122,9 @@ export interface Robot { * Get the current screen orientation. */ getOrientation(): Promise; + + /** + * Fold or unfold a device. Possible actions: (fold, unfold) + */ + changeDevicePosture(posture: PostureStates): Promise; } diff --git a/src/server.ts b/src/server.ts index 3d19c84..87f00d6 100644 --- a/src/server.ts +++ b/src/server.ts @@ -474,6 +474,19 @@ export const createMcpServer = (): McpServer => { } ); + tool( + "mobile_change_posture", + "Fold or unfold the device.", + { + posture: z.enum(["fold", "unfold"]).describe("The desired posture") + }, + async ({ posture }) => { + requireRobot(); + await robot!.changeDevicePosture(posture); + return `Changed device posture to ${posture}`; + } + ); + // async check for latest agent version checkForLatestAgentVersion().then();