UNPKG

@gui-agent/operator-adb

Version:
1 lines 20.6 kB
{"version":3,"file":"AdbOperator.mjs","sources":["webpack://@gui-agent/operator-adb/./src/AdbOperator.ts"],"sourcesContent":["/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nimport {\n Coordinates,\n SupportedActionType,\n ScreenshotOutput,\n ExecuteParams,\n ExecuteOutput,\n BaseAction,\n HotkeyAction,\n} from '@gui-agent/shared/types';\nimport { Operator, ScreenContext } from '@gui-agent/shared/base';\nimport { ConsoleLogger, LogLevel } from '@agent-infra/logger';\n\nimport { ADB } from 'appium-adb';\n\nconst defaultLogger = new ConsoleLogger(undefined, LogLevel.DEBUG);\nconst yadbCommand =\n 'app_process -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main';\nconst screenshotPathOnAndroid = '/data/local/tmp/ui_tars_screenshot.png';\nconst screenshotPathOnLocal = path.join(os.homedir(), 'Downloads', 'ui_tars_screenshot.png');\n\nexport class AdbOperator extends Operator {\n private logger: ConsoleLogger;\n private _deviceId: string | null = null;\n private _adb: ADB | null = null;\n private _hasPushedYadb = false;\n private _screenContext: ScreenContext | null = null;\n\n constructor(logger: ConsoleLogger = defaultLogger) {\n super();\n this.logger = logger.spawn('[AdbOperator]');\n }\n\n protected async initialize(): Promise<void> {\n this._deviceId = await this.getConnectedDevices();\n this._adb = await ADB.createADB({\n udid: this._deviceId,\n adbExecTimeout: 60000,\n });\n this._screenContext = await this.calculateScreenContext(this._adb);\n }\n\n protected supportedActions(): Array<SupportedActionType> {\n throw new Error('Method not implemented.');\n }\n\n protected screenContext(): ScreenContext {\n // Assert that _screenContext is not null\n if (!this._screenContext) {\n throw new Error('The Operator not initialized');\n }\n return this._screenContext;\n }\n\n protected async screenshot(): Promise<ScreenshotOutput> {\n // Assert that _adb is not null\n if (!this._adb) {\n throw new Error('The Operator not initialized');\n }\n return await this.screenshotWithFallback();\n }\n\n protected async execute(params: ExecuteParams): Promise<ExecuteOutput> {\n const { actions } = params;\n for (const action of actions) {\n this.logger.info('execute action', action);\n await this.singleActionExecutor(action);\n }\n return {\n status: 'success',\n };\n }\n\n private async singleActionExecutor(action: BaseAction) {\n const { type: actionType, inputs: actionInputs } = action;\n switch (actionType) {\n case 'click': {\n const { point } = actionInputs;\n if (!point) {\n throw new Error('point is required when click');\n }\n const { realX, realY } = await this.calculateRealCoords(point);\n await this.handleClick(realX, realY);\n break;\n }\n case 'long_press': {\n const { point } = actionInputs;\n if (!point) {\n throw new Error('point is required when click');\n }\n const { realX, realY } = await this.calculateRealCoords(point);\n this.handleSwipe({ x: realX, y: realY }, { x: realX, y: realY }, 1500);\n break;\n }\n case 'swipe':\n case 'drag': {\n const { start: startPoint, end: endPoint } = actionInputs;\n if (!startPoint) {\n throw new Error('start point is required when swipe/drag');\n }\n if (!endPoint) {\n throw new Error('end point is required when swipe/drag');\n }\n const { realX: startX, realY: startY } = await this.calculateRealCoords(startPoint);\n const { realX: endX, realY: endY } = await this.calculateRealCoords(endPoint);\n this.handleSwipe({ x: startX, y: startY }, { x: endX, y: endY }, 300);\n break;\n }\n case 'scroll': {\n const { direction, point } = actionInputs;\n if (!direction) {\n throw new Error(`Direction required when scroll`);\n }\n this.handleScroll(direction, point);\n break;\n }\n case 'type': {\n const { content } = actionInputs;\n this.handleType(content);\n break;\n }\n case 'hotkey': {\n const { key } = actionInputs;\n await this.handleHotkey(key);\n break;\n }\n case 'open_app':\n throw new Error('The device does NOT support open app directly');\n case 'home':\n case 'press_home': {\n await this.handleHotkey('home');\n break;\n }\n case 'back':\n case 'press_back': {\n await this.handleHotkey('back');\n break;\n }\n default:\n this.logger.warn(`[AdbOperator] Unsupported action: ${actionType}`);\n throw new Error(`Unsupported action: ${actionType}`);\n }\n }\n\n private async calculateRealCoords(\n coords: Coordinates,\n ): Promise<{ realX: number; realY: number }> {\n if (!coords.normalized) {\n if (!coords.raw) {\n throw new Error('Invalide coordinates');\n }\n return {\n realX: coords.raw.x,\n realY: coords.raw.y,\n };\n }\n const screenContext = await this.getScreenContext();\n return {\n realX: coords.normalized.x * screenContext.screenWidth * screenContext.scaleX,\n realY: coords.normalized.y * screenContext.screenHeight * screenContext.scaleY,\n };\n }\n\n /**\n * Get all connected Android device IDs\n * @returns List of device IDs\n * @throws Error when unable to retrieve device list\n */\n private async getConnectedDevices(): Promise<string> {\n const execPromise = promisify(exec);\n try {\n const { stdout } = await execPromise('adb devices');\n const devices = stdout\n .split('\\n')\n .slice(1) // Skip the first line \"List of devices attached\"\n .map((line) => {\n const [id, status] = line.split('\\t');\n return { id, status };\n })\n .filter(({ id, status }) => id && status && status.trim() === 'device')\n .map(({ id }) => id);\n\n if (devices.length === 0) {\n throw new Error('No available Android devices found');\n }\n if (devices.length > 1) {\n this.logger.warn(\n `Multiple devices detected: ${devices.join(',')}. Using the first: ${devices[0]}`,\n );\n }\n return devices[0];\n } catch (error) {\n this.logger.error('Failed to get devices:', error);\n throw error;\n }\n }\n\n private async calculateScreenContext(adb: ADB) {\n const screenSize = await adb.getScreenSize();\n this.logger.debug('getScreenSize', screenSize);\n if (!screenSize) {\n throw new Error('Unable to get screenSize');\n }\n\n // handle string format \"width x height\"\n const match = screenSize.match(/(\\d+)x(\\d+)/);\n if (!match || match.length < 3) {\n throw new Error(`Unable to parse screenSize: ${screenSize}`);\n }\n const width = Number.parseInt(match[1], 10);\n const height = Number.parseInt(match[2], 10);\n\n // Get device display density\n const densityNum = await adb.getScreenDensity();\n this.logger.debug('getScreenDensity', densityNum);\n // Standard density is 160, calculate the ratio\n const deviceRatio = Number(densityNum) / 160;\n this.logger.debug('deviceRatio', deviceRatio);\n const adjustedSize = this.reverseAdjustCoordinates(deviceRatio, width, height);\n this.logger.debug('adjustedWidth', adjustedSize);\n\n return {\n screenWidth: width,\n screenHeight: height,\n scaleX: 1,\n scaleY: 1,\n };\n }\n\n private reverseAdjustCoordinates(ratio: number, x: number, y: number): { x: number; y: number } {\n return {\n x: Math.round(x / ratio),\n y: Math.round(y / ratio),\n };\n }\n\n async screenshotWithFallback(): Promise<ScreenshotOutput> {\n let screenshotBuffer;\n try {\n screenshotBuffer = await this._adb!.takeScreenshot(null);\n } catch (error) {\n this.logger.warn('screenshotWithFallback', (error as Error).message);\n // TODO: does the appium supports exec-out?\n try {\n const result = await this._adb!.shell(`screencap -p ${screenshotPathOnAndroid}`);\n this.logger.debug('screenshotWithFallback result of screencap:', result);\n } catch (error) {\n // screenshot which is forbidden by app\n await this.executeWithYadb(`-screenshot ${screenshotPathOnAndroid}`);\n }\n await this._adb!.pull(screenshotPathOnAndroid, screenshotPathOnLocal);\n screenshotBuffer = await fs.promises.readFile(screenshotPathOnLocal);\n }\n const base64 = screenshotBuffer.toString('base64');\n return {\n status: 'success',\n base64,\n };\n }\n\n private async handleClick(x: number, y: number): Promise<void> {\n // Use adjusted coordinates\n await this._adb!.shell(`input tap ${x} ${y}`);\n }\n\n private async handleType(text: string): Promise<void> {\n if (!text) {\n throw new Error('The content of type is empty');\n }\n\n const isChinese = /[\\p{Script=Han}\\p{sc=Hani}]/u.test(text);\n // for pure ASCII characters, directly use inputText\n if (!isChinese) {\n await this._adb!.inputText(text);\n return;\n }\n // for non-ASCII characters, use yadb\n await this.executeWithYadb(`-keyboard \"${text}\"`);\n }\n\n private async handleHotkey(keyStr: string) {\n if (!keyStr) {\n throw new Error('The hotkey is empty');\n }\n const keyMap: Record<string, number> = {\n home: 3, // KEYCODE_HOME, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_HOME\n back: 4, // KEYCODE_BACK, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_BACK\n menu: 82, // KEYCODE_MENU, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_MENU\n power: 26, // KEYCODE_POWER, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_POWER\n volume_up: 24, // KEYCODE_VOLUME_UP, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_VOLUME_UP\n volumeup: 24,\n volume_down: 25, // KEYCODE_VOLUME_DOWN, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_VOLUME_DOWN\n volumedown: 25,\n mute: 164, // KEYCODE_VOLUME_MUTE, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_VOLUME_MUTE\n enter: 66, // KEYCODE_ENTER, https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_ENTER\n delete: 112,\n lock: 26,\n // tab: 61,\n // arrowup: 19,\n // arrow_up: 19,\n // arrowdown: 20,\n // arrow_down: 20,\n // arrowleft: 21,\n // arrow_left: 21,\n // arrowright: 22,\n // arrowr_ight: 22,\n // escape: 111,\n // end: 123,\n };\n const keyCode = keyMap[keyStr.toLowerCase()];\n if (!keyCode) {\n throw new Error(`Unsupported key: ${keyStr}`);\n }\n this._adb!.keyevent(keyCode);\n }\n\n private async handleSwipe(\n from: { x: number; y: number },\n to: { x: number; y: number },\n duration: number, // ms\n ): Promise<void> {\n await this._adb!.shell(`input swipe ${from.x} ${from.y} ${to.x} ${to.y} ${duration}`);\n }\n\n private async handleScroll(direction: string, point?: Coordinates) {\n const screenContext = await this.getScreenContext();\n let startX = screenContext.screenWidth / 2;\n let startY = screenContext.screenHeight / 2;\n if (point) {\n const { realX, realY } = await this.calculateRealCoords(point);\n startX = realX;\n startY = realY;\n }\n let endX = startX;\n let endY = startY;\n switch (direction.toLowerCase()) {\n case 'up':\n endY = endY - 200;\n break;\n case 'down':\n endY = endY + 200;\n break;\n case 'left':\n endX = endX - 200;\n break;\n case 'right':\n endX = endX + 200;\n break;\n default:\n throw new Error(`Unsupported scroll direction: ${direction}`);\n }\n this.handleSwipe({ x: startX, y: startY }, { x: endX, y: endY }, 300);\n }\n\n /**\n * @param subCommand, such as:\n * -keyboard \"${keyboardContent}\n */\n private async executeWithYadb(subCommand: string): Promise<void> {\n if (!this._hasPushedYadb) {\n // the size of yadb just 12kB, just adb push it every time initailied\n const yadbBin = path.join(__dirname, '../bin/yadb');\n await this._adb!.push(yadbBin, '/data/local/tmp');\n this._hasPushedYadb = true;\n }\n await this._adb!.shell(`${yadbCommand} ${subCommand}`);\n }\n}\n"],"names":["defaultLogger","ConsoleLogger","undefined","LogLevel","yadbCommand","screenshotPathOnAndroid","screenshotPathOnLocal","path","os","AdbOperator","Operator","ADB","Error","params","actions","action","actionType","actionInputs","point","realX","realY","startPoint","endPoint","startX","startY","endX","endY","direction","content","key","coords","screenContext","execPromise","promisify","exec","stdout","devices","line","id","status","error","adb","screenSize","match","width","Number","height","densityNum","deviceRatio","adjustedSize","ratio","x","y","Math","screenshotBuffer","result","fs","base64","text","isChinese","keyStr","keyMap","keyCode","from","to","duration","subCommand","yadbBin","__dirname","logger"],"mappings":"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"}