@midscene/android 1.6.0 → 1.6.1-beta-20260327104111.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/es/cli.mjs CHANGED
@@ -13,7 +13,7 @@ import { defineAction, defineActionClearInput, defineActionCursorMove, defineAct
13
13
  import { getTmpFile, sleep } from "@midscene/core/utils";
14
14
  import { MIDSCENE_ADB_PATH, MIDSCENE_ADB_REMOTE_HOST, MIDSCENE_ADB_REMOTE_PORT, MIDSCENE_ANDROID_IME_STRATEGY, globalConfigManager } from "@midscene/shared/env";
15
15
  import { createImgBase64ByFormat, isValidImageBuffer } from "@midscene/shared/img";
16
- import { ADB } from "appium-adb";
16
+ import { ADB as external_appium_adb_ADB } from "appium-adb";
17
17
  var __webpack_modules__ = {
18
18
  "./src/scrcpy-manager.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
19
19
  __webpack_require__.d(__webpack_exports__, {
@@ -870,7 +870,7 @@ class AndroidDevice {
870
870
  const androidAdbPath = this.options?.androidAdbPath || globalConfigManager.getEnvConfigValue(MIDSCENE_ADB_PATH);
871
871
  const remoteAdbHost = this.options?.remoteAdbHost || globalConfigManager.getEnvConfigValue(MIDSCENE_ADB_REMOTE_HOST);
872
872
  const remoteAdbPort = this.options?.remoteAdbPort || globalConfigManager.getEnvConfigValue(MIDSCENE_ADB_REMOTE_PORT);
873
- this.adb = new ADB({
873
+ this.adb = new external_appium_adb_ADB({
874
874
  udid: this.deviceId,
875
875
  adbExecTimeout: 60000,
876
876
  executable: androidAdbPath ? {
@@ -1800,7 +1800,7 @@ const createPlatformActions = (device)=>({
1800
1800
  const debugUtils = (0, logger_.getDebug)('android:utils');
1801
1801
  async function getConnectedDevices() {
1802
1802
  try {
1803
- const adb = await ADB.createADB({
1803
+ const adb = await external_appium_adb_ADB.createADB({
1804
1804
  adbExecTimeout: 60000
1805
1805
  });
1806
1806
  const devices = await adb.getConnectedDevices();
@@ -1918,7 +1918,7 @@ class AndroidMidsceneTools extends BaseMidsceneTools {
1918
1918
  const tools = new AndroidMidsceneTools();
1919
1919
  runToolsCLI(tools, 'midscene-android', {
1920
1920
  stripPrefix: 'android_',
1921
- version: "1.6.0"
1921
+ version: "1.6.1-beta-20260327104111.0"
1922
1922
  }).catch((e)=>{
1923
1923
  if (!(e instanceof CLIError)) console.error(e);
1924
1924
  process.exit(e instanceof CLIError ? e.exitCode : 1);
package/dist/es/index.mjs CHANGED
@@ -1797,6 +1797,38 @@ const defaultAppNameMapping = {
1797
1797
  WhatsApp: 'com.whatsapp'
1798
1798
  };
1799
1799
  const debugUtils = (0, logger_.getDebug)('android:utils');
1800
+ const DETAIL_LOOKUP_ADB_TIMEOUT_MS = 8000;
1801
+ const DETAIL_LOOKUP_STEP_TIMEOUT_MS = 2000;
1802
+ function cleanProp(value) {
1803
+ const normalized = value?.trim();
1804
+ return normalized ? normalized : void 0;
1805
+ }
1806
+ function parseResolution(stdout) {
1807
+ const overrideSize = stdout.match(/Override size:\s*([^\r\n]+)/);
1808
+ if (overrideSize?.[1]) return overrideSize[1].trim();
1809
+ const physicalSize = stdout.match(/Physical size:\s*([^\r\n]+)/);
1810
+ if (physicalSize?.[1]) return physicalSize[1].trim();
1811
+ }
1812
+ async function withTimeout(promise, timeoutMs, label) {
1813
+ let timer;
1814
+ try {
1815
+ return await Promise.race([
1816
+ promise,
1817
+ new Promise((_, reject)=>{
1818
+ timer = setTimeout(()=>{
1819
+ reject(new Error(`${label} timed out after ${timeoutMs}ms`));
1820
+ }, timeoutMs);
1821
+ })
1822
+ ]);
1823
+ } finally{
1824
+ if (timer) clearTimeout(timer);
1825
+ }
1826
+ }
1827
+ async function createAdbForDetailLookup() {
1828
+ return await ADB.createADB({
1829
+ adbExecTimeout: DETAIL_LOOKUP_ADB_TIMEOUT_MS
1830
+ });
1831
+ }
1800
1832
  async function getConnectedDevices() {
1801
1833
  try {
1802
1834
  const adb = await ADB.createADB({
@@ -1812,6 +1844,41 @@ async function getConnectedDevices() {
1812
1844
  });
1813
1845
  }
1814
1846
  }
1847
+ async function getConnectedDevicesWithDetails() {
1848
+ const devices = await getConnectedDevices();
1849
+ if (0 === devices.length) return [];
1850
+ return await Promise.all(devices.map(async (device)=>{
1851
+ const detailedDevice = {
1852
+ ...device
1853
+ };
1854
+ try {
1855
+ const adb = await createAdbForDetailLookup();
1856
+ adb.setDeviceId(device.udid);
1857
+ const [modelResult, brandResult, sizeResult, densityResult] = await Promise.allSettled([
1858
+ withTimeout(adb.shell([
1859
+ 'getprop',
1860
+ 'ro.product.model'
1861
+ ]), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android model lookup for ${device.udid}`),
1862
+ withTimeout(adb.shell([
1863
+ 'getprop',
1864
+ 'ro.product.brand'
1865
+ ]), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android brand lookup for ${device.udid}`),
1866
+ withTimeout(adb.shell([
1867
+ 'wm',
1868
+ 'size'
1869
+ ]), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android resolution lookup for ${device.udid}`),
1870
+ withTimeout(adb.getScreenDensity(), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android density lookup for ${device.udid}`)
1871
+ ]);
1872
+ if ('fulfilled' === modelResult.status) detailedDevice.model = cleanProp(modelResult.value);
1873
+ if ('fulfilled' === brandResult.status) detailedDevice.brand = cleanProp(brandResult.value);
1874
+ if ('fulfilled' === sizeResult.status) detailedDevice.resolution = parseResolution(sizeResult.value);
1875
+ if ('fulfilled' === densityResult.status && 'number' == typeof densityResult.value) detailedDevice.density = densityResult.value;
1876
+ } catch (error) {
1877
+ debugUtils(`Failed to enrich Android device ${device.udid}:`, error);
1878
+ }
1879
+ return detailedDevice;
1880
+ }));
1881
+ }
1815
1882
  function agent_define_property(obj, key, value) {
1816
1883
  if (key in obj) Object.defineProperty(obj, key, {
1817
1884
  value: value,
@@ -1914,4 +1981,4 @@ class AndroidMidsceneTools extends BaseMidsceneTools {
1914
1981
  ];
1915
1982
  }
1916
1983
  }
1917
- export { AndroidAgent, AndroidDevice, AndroidMidsceneTools, ScrcpyDeviceAdapter, agentFromAdbDevice, getConnectedDevices, overrideAIConfig };
1984
+ export { AndroidAgent, AndroidDevice, AndroidMidsceneTools, ScrcpyDeviceAdapter, agentFromAdbDevice, getConnectedDevices, getConnectedDevicesWithDetails, overrideAIConfig };
@@ -12,7 +12,7 @@ import { defineAction, defineActionClearInput, defineActionCursorMove, defineAct
12
12
  import { getTmpFile, sleep } from "@midscene/core/utils";
13
13
  import { MIDSCENE_ADB_PATH, MIDSCENE_ADB_REMOTE_HOST, MIDSCENE_ADB_REMOTE_PORT, MIDSCENE_ANDROID_IME_STRATEGY, globalConfigManager } from "@midscene/shared/env";
14
14
  import { createImgBase64ByFormat, isValidImageBuffer } from "@midscene/shared/img";
15
- import { ADB } from "appium-adb";
15
+ import { ADB as external_appium_adb_ADB } from "appium-adb";
16
16
  var __webpack_modules__ = {
17
17
  "./src/scrcpy-manager.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
18
18
  __webpack_require__.d(__webpack_exports__, {
@@ -869,7 +869,7 @@ class AndroidDevice {
869
869
  const androidAdbPath = this.options?.androidAdbPath || globalConfigManager.getEnvConfigValue(MIDSCENE_ADB_PATH);
870
870
  const remoteAdbHost = this.options?.remoteAdbHost || globalConfigManager.getEnvConfigValue(MIDSCENE_ADB_REMOTE_HOST);
871
871
  const remoteAdbPort = this.options?.remoteAdbPort || globalConfigManager.getEnvConfigValue(MIDSCENE_ADB_REMOTE_PORT);
872
- this.adb = new ADB({
872
+ this.adb = new external_appium_adb_ADB({
873
873
  udid: this.deviceId,
874
874
  adbExecTimeout: 60000,
875
875
  executable: androidAdbPath ? {
@@ -1799,7 +1799,7 @@ const createPlatformActions = (device)=>({
1799
1799
  const debugUtils = (0, logger_.getDebug)('android:utils');
1800
1800
  async function getConnectedDevices() {
1801
1801
  try {
1802
- const adb = await ADB.createADB({
1802
+ const adb = await external_appium_adb_ADB.createADB({
1803
1803
  adbExecTimeout: 60000
1804
1804
  });
1805
1805
  const devices = await adb.getConnectedDevices();
@@ -1921,7 +1921,7 @@ class AndroidMCPServer extends BaseMCPServer {
1921
1921
  constructor(toolsManager){
1922
1922
  super({
1923
1923
  name: '@midscene/android-mcp',
1924
- version: "1.6.0",
1924
+ version: "1.6.1-beta-20260327104111.0",
1925
1925
  description: 'Control the Android device using natural language commands'
1926
1926
  }, toolsManager);
1927
1927
  }
package/dist/lib/cli.js CHANGED
@@ -1933,7 +1933,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1933
1933
  const tools = new AndroidMidsceneTools();
1934
1934
  (0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-android', {
1935
1935
  stripPrefix: 'android_',
1936
- version: "1.6.0"
1936
+ version: "1.6.1-beta-20260327104111.0"
1937
1937
  }).catch((e)=>{
1938
1938
  if (!(e instanceof cli_namespaceObject.CLIError)) console.error(e);
1939
1939
  process.exit(e instanceof cli_namespaceObject.CLIError ? e.exitCode : 1);
package/dist/lib/index.js CHANGED
@@ -458,13 +458,14 @@ var __webpack_exports__ = {};
458
458
  (()=>{
459
459
  __webpack_require__.r(__webpack_exports__);
460
460
  __webpack_require__.d(__webpack_exports__, {
461
- AndroidMidsceneTools: ()=>AndroidMidsceneTools,
462
- getConnectedDevices: ()=>getConnectedDevices,
463
- overrideAIConfig: ()=>env_namespaceObject.overrideAIConfig,
464
461
  AndroidAgent: ()=>AndroidAgent,
465
462
  agentFromAdbDevice: ()=>agentFromAdbDevice,
463
+ getConnectedDevicesWithDetails: ()=>getConnectedDevicesWithDetails,
466
464
  ScrcpyDeviceAdapter: ()=>ScrcpyDeviceAdapter,
467
- AndroidDevice: ()=>AndroidDevice
465
+ AndroidMidsceneTools: ()=>AndroidMidsceneTools,
466
+ AndroidDevice: ()=>AndroidDevice,
467
+ overrideAIConfig: ()=>env_namespaceObject.overrideAIConfig,
468
+ getConnectedDevices: ()=>getConnectedDevices
468
469
  });
469
470
  const external_node_assert_namespaceObject = require("node:assert");
470
471
  var external_node_assert_default = /*#__PURE__*/ __webpack_require__.n(external_node_assert_namespaceObject);
@@ -1831,6 +1832,38 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1831
1832
  WhatsApp: 'com.whatsapp'
1832
1833
  };
1833
1834
  const debugUtils = (0, logger_.getDebug)('android:utils');
1835
+ const DETAIL_LOOKUP_ADB_TIMEOUT_MS = 8000;
1836
+ const DETAIL_LOOKUP_STEP_TIMEOUT_MS = 2000;
1837
+ function cleanProp(value) {
1838
+ const normalized = value?.trim();
1839
+ return normalized ? normalized : void 0;
1840
+ }
1841
+ function parseResolution(stdout) {
1842
+ const overrideSize = stdout.match(/Override size:\s*([^\r\n]+)/);
1843
+ if (overrideSize?.[1]) return overrideSize[1].trim();
1844
+ const physicalSize = stdout.match(/Physical size:\s*([^\r\n]+)/);
1845
+ if (physicalSize?.[1]) return physicalSize[1].trim();
1846
+ }
1847
+ async function withTimeout(promise, timeoutMs, label) {
1848
+ let timer;
1849
+ try {
1850
+ return await Promise.race([
1851
+ promise,
1852
+ new Promise((_, reject)=>{
1853
+ timer = setTimeout(()=>{
1854
+ reject(new Error(`${label} timed out after ${timeoutMs}ms`));
1855
+ }, timeoutMs);
1856
+ })
1857
+ ]);
1858
+ } finally{
1859
+ if (timer) clearTimeout(timer);
1860
+ }
1861
+ }
1862
+ async function createAdbForDetailLookup() {
1863
+ return await external_appium_adb_namespaceObject.ADB.createADB({
1864
+ adbExecTimeout: DETAIL_LOOKUP_ADB_TIMEOUT_MS
1865
+ });
1866
+ }
1834
1867
  async function getConnectedDevices() {
1835
1868
  try {
1836
1869
  const adb = await external_appium_adb_namespaceObject.ADB.createADB({
@@ -1846,6 +1879,41 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1846
1879
  });
1847
1880
  }
1848
1881
  }
1882
+ async function getConnectedDevicesWithDetails() {
1883
+ const devices = await getConnectedDevices();
1884
+ if (0 === devices.length) return [];
1885
+ return await Promise.all(devices.map(async (device)=>{
1886
+ const detailedDevice = {
1887
+ ...device
1888
+ };
1889
+ try {
1890
+ const adb = await createAdbForDetailLookup();
1891
+ adb.setDeviceId(device.udid);
1892
+ const [modelResult, brandResult, sizeResult, densityResult] = await Promise.allSettled([
1893
+ withTimeout(adb.shell([
1894
+ 'getprop',
1895
+ 'ro.product.model'
1896
+ ]), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android model lookup for ${device.udid}`),
1897
+ withTimeout(adb.shell([
1898
+ 'getprop',
1899
+ 'ro.product.brand'
1900
+ ]), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android brand lookup for ${device.udid}`),
1901
+ withTimeout(adb.shell([
1902
+ 'wm',
1903
+ 'size'
1904
+ ]), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android resolution lookup for ${device.udid}`),
1905
+ withTimeout(adb.getScreenDensity(), DETAIL_LOOKUP_STEP_TIMEOUT_MS, `Android density lookup for ${device.udid}`)
1906
+ ]);
1907
+ if ('fulfilled' === modelResult.status) detailedDevice.model = cleanProp(modelResult.value);
1908
+ if ('fulfilled' === brandResult.status) detailedDevice.brand = cleanProp(brandResult.value);
1909
+ if ('fulfilled' === sizeResult.status) detailedDevice.resolution = parseResolution(sizeResult.value);
1910
+ if ('fulfilled' === densityResult.status && 'number' == typeof densityResult.value) detailedDevice.density = densityResult.value;
1911
+ } catch (error) {
1912
+ debugUtils(`Failed to enrich Android device ${device.udid}:`, error);
1913
+ }
1914
+ return detailedDevice;
1915
+ }));
1916
+ }
1849
1917
  function agent_define_property(obj, key, value) {
1850
1918
  if (key in obj) Object.defineProperty(obj, key, {
1851
1919
  value: value,
@@ -1956,6 +2024,7 @@ exports.AndroidMidsceneTools = __webpack_exports__.AndroidMidsceneTools;
1956
2024
  exports.ScrcpyDeviceAdapter = __webpack_exports__.ScrcpyDeviceAdapter;
1957
2025
  exports.agentFromAdbDevice = __webpack_exports__.agentFromAdbDevice;
1958
2026
  exports.getConnectedDevices = __webpack_exports__.getConnectedDevices;
2027
+ exports.getConnectedDevicesWithDetails = __webpack_exports__.getConnectedDevicesWithDetails;
1959
2028
  exports.overrideAIConfig = __webpack_exports__.overrideAIConfig;
1960
2029
  for(var __rspack_i in __webpack_exports__)if (-1 === [
1961
2030
  "AndroidAgent",
@@ -1964,6 +2033,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
1964
2033
  "ScrcpyDeviceAdapter",
1965
2034
  "agentFromAdbDevice",
1966
2035
  "getConnectedDevices",
2036
+ "getConnectedDevicesWithDetails",
1967
2037
  "overrideAIConfig"
1968
2038
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
1969
2039
  Object.defineProperty(exports, '__esModule', {
@@ -1952,7 +1952,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1952
1952
  constructor(toolsManager){
1953
1953
  super({
1954
1954
  name: '@midscene/android-mcp',
1955
- version: "1.6.0",
1955
+ version: "1.6.1-beta-20260327104111.0",
1956
1956
  description: 'Control the Android device using natural language commands'
1957
1957
  }, toolsManager);
1958
1958
  }
@@ -60,6 +60,13 @@ export declare type AndroidAgentOpt = AgentOpt & {
60
60
  appNameMapping?: Record<string, string>;
61
61
  };
62
62
 
63
+ export declare interface AndroidConnectedDevice extends Device {
64
+ model?: string;
65
+ brand?: string;
66
+ resolution?: string;
67
+ density?: number;
68
+ }
69
+
63
70
  export declare class AndroidDevice implements AbstractInterface {
64
71
  private deviceId;
65
72
  private yadbPushed;
@@ -243,6 +250,8 @@ declare interface DevicePhysicalInfo {
243
250
 
244
251
  export declare function getConnectedDevices(): Promise<Device[]>;
245
252
 
253
+ export declare function getConnectedDevicesWithDetails(): Promise<AndroidConnectedDevice[]>;
254
+
246
255
  export { overrideAIConfig }
247
256
 
248
257
  declare interface ResolvedScrcpyConfig {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/android",
3
- "version": "1.6.0",
3
+ "version": "1.6.1-beta-20260327104111.0",
4
4
  "description": "Android automation library for Midscene",
5
5
  "keywords": [
6
6
  "Android UI automation",
@@ -41,8 +41,8 @@
41
41
  "@yume-chan/stream-extra": "2.1.0",
42
42
  "appium-adb": "12.12.1",
43
43
  "sharp": "^0.34.3",
44
- "@midscene/shared": "1.6.0",
45
- "@midscene/core": "1.6.0"
44
+ "@midscene/core": "1.6.1-beta-20260327104111.0",
45
+ "@midscene/shared": "1.6.1-beta-20260327104111.0"
46
46
  },
47
47
  "optionalDependencies": {
48
48
  "@ffmpeg-installer/ffmpeg": "^1.1.0"
@@ -56,7 +56,7 @@
56
56
  "tsx": "^4.19.2",
57
57
  "vitest": "3.0.5",
58
58
  "zod": "3.24.3",
59
- "@midscene/playground": "1.6.0"
59
+ "@midscene/playground": "1.6.1-beta-20260327104111.0"
60
60
  },
61
61
  "license": "MIT",
62
62
  "scripts": {