@midscene/android 1.5.4-beta-20260310030546.0 → 1.5.4

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
@@ -706,6 +706,12 @@ class AndroidDevice {
706
706
  ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
707
707
  locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
708
708
  }),
709
+ sample: {
710
+ value: 'test@example.com',
711
+ locate: {
712
+ prompt: 'the email input field'
713
+ }
714
+ },
709
715
  call: async (param)=>{
710
716
  const element = param.locate;
711
717
  if ('typeOnly' !== param.mode) await this.clearInput(element);
@@ -773,6 +779,11 @@ class AndroidDevice {
773
779
  duration: z.number().optional().describe('The duration of the long press in milliseconds'),
774
780
  locate: getMidsceneLocationSchema().describe('The element to be long pressed')
775
781
  }),
782
+ sample: {
783
+ locate: {
784
+ prompt: 'the message bubble'
785
+ }
786
+ },
776
787
  call: async (param)=>{
777
788
  const element = param.locate;
778
789
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -792,6 +803,12 @@ class AndroidDevice {
792
803
  duration: z.number().optional().describe('The duration of the pull (in milliseconds)'),
793
804
  locate: getMidsceneLocationSchema().optional().describe('The element to start the pull from (optional)')
794
805
  }),
806
+ sample: {
807
+ direction: 'down',
808
+ locate: {
809
+ prompt: 'the center of the content list area'
810
+ }
811
+ },
795
812
  call: async (param)=>{
796
813
  const element = param.locate;
797
814
  const startPoint = element ? {
@@ -961,6 +978,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
961
978
  }
962
979
  async getScreenSize() {
963
980
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
981
+ debugDevice(`getScreenSize: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedSize=${!!this.cachedScreenSize}`);
964
982
  if (shouldCache && this.cachedScreenSize) return this.cachedScreenSize;
965
983
  const adb = await this.getAdb();
966
984
  if ('number' == typeof this.options?.displayId) try {
@@ -1094,6 +1112,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1094
1112
  }
1095
1113
  async getDisplayOrientation() {
1096
1114
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1115
+ debugDevice(`getDisplayOrientation: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedOrientation=${null !== this.cachedOrientation}`);
1097
1116
  if (shouldCache && null !== this.cachedOrientation) return this.cachedOrientation;
1098
1117
  const adb = await this.getAdb();
1099
1118
  let orientation = 0;
@@ -1138,6 +1157,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1138
1157
  }
1139
1158
  async getAdjustScale() {
1140
1159
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1160
+ debugDevice(`getAdjustScale: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedScale=${!!this.cachedAdjustScale}`);
1141
1161
  if (shouldCache && this.cachedAdjustScale) return this.cachedAdjustScale;
1142
1162
  const physical = await this.getOrientedPhysicalSize();
1143
1163
  const { width: logicalW, height: logicalH } = await this.size();
@@ -1723,6 +1743,9 @@ const createPlatformActions = (device)=>({
1723
1743
  description: 'Execute ADB shell command on Android device',
1724
1744
  interfaceAlias: 'runAdbShell',
1725
1745
  paramSchema: runAdbShellParamSchema,
1746
+ sample: {
1747
+ command: 'dumpsys window displays | grep -E "mCurrentFocus"'
1748
+ },
1726
1749
  call: async (param)=>{
1727
1750
  if (!param.command || '' === param.command.trim()) throw new Error('RunAdbShell requires a non-empty command parameter');
1728
1751
  const adb = await device.getAdb();
@@ -1734,6 +1757,9 @@ const createPlatformActions = (device)=>({
1734
1757
  description: 'Launch an Android app or URL',
1735
1758
  interfaceAlias: 'launch',
1736
1759
  paramSchema: launchParamSchema,
1760
+ sample: {
1761
+ uri: 'com.example.app'
1762
+ },
1737
1763
  call: async (param)=>{
1738
1764
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
1739
1765
  await device.launch(param.uri);
@@ -1881,7 +1907,8 @@ class AndroidMidsceneTools extends BaseMidsceneTools {
1881
1907
  }
1882
1908
  const tools = new AndroidMidsceneTools();
1883
1909
  runToolsCLI(tools, 'midscene-android', {
1884
- stripPrefix: 'android_'
1910
+ stripPrefix: 'android_',
1911
+ version: "1.5.4"
1885
1912
  }).catch((e)=>{
1886
1913
  if (!(e instanceof CLIError)) console.error(e);
1887
1914
  process.exit(e instanceof CLIError ? e.exitCode : 1);
package/dist/es/index.mjs CHANGED
@@ -609,6 +609,12 @@ class AndroidDevice {
609
609
  ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
610
610
  locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
611
611
  }),
612
+ sample: {
613
+ value: 'test@example.com',
614
+ locate: {
615
+ prompt: 'the email input field'
616
+ }
617
+ },
612
618
  call: async (param)=>{
613
619
  const element = param.locate;
614
620
  if ('typeOnly' !== param.mode) await this.clearInput(element);
@@ -676,6 +682,11 @@ class AndroidDevice {
676
682
  duration: z.number().optional().describe('The duration of the long press in milliseconds'),
677
683
  locate: getMidsceneLocationSchema().describe('The element to be long pressed')
678
684
  }),
685
+ sample: {
686
+ locate: {
687
+ prompt: 'the message bubble'
688
+ }
689
+ },
679
690
  call: async (param)=>{
680
691
  const element = param.locate;
681
692
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -695,6 +706,12 @@ class AndroidDevice {
695
706
  duration: z.number().optional().describe('The duration of the pull (in milliseconds)'),
696
707
  locate: getMidsceneLocationSchema().optional().describe('The element to start the pull from (optional)')
697
708
  }),
709
+ sample: {
710
+ direction: 'down',
711
+ locate: {
712
+ prompt: 'the center of the content list area'
713
+ }
714
+ },
698
715
  call: async (param)=>{
699
716
  const element = param.locate;
700
717
  const startPoint = element ? {
@@ -864,6 +881,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
864
881
  }
865
882
  async getScreenSize() {
866
883
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
884
+ debugDevice(`getScreenSize: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedSize=${!!this.cachedScreenSize}`);
867
885
  if (shouldCache && this.cachedScreenSize) return this.cachedScreenSize;
868
886
  const adb = await this.getAdb();
869
887
  if ('number' == typeof this.options?.displayId) try {
@@ -997,6 +1015,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
997
1015
  }
998
1016
  async getDisplayOrientation() {
999
1017
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1018
+ debugDevice(`getDisplayOrientation: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedOrientation=${null !== this.cachedOrientation}`);
1000
1019
  if (shouldCache && null !== this.cachedOrientation) return this.cachedOrientation;
1001
1020
  const adb = await this.getAdb();
1002
1021
  let orientation = 0;
@@ -1041,6 +1060,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1041
1060
  }
1042
1061
  async getAdjustScale() {
1043
1062
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1063
+ debugDevice(`getAdjustScale: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedScale=${!!this.cachedAdjustScale}`);
1044
1064
  if (shouldCache && this.cachedAdjustScale) return this.cachedAdjustScale;
1045
1065
  const physical = await this.getOrientedPhysicalSize();
1046
1066
  const { width: logicalW, height: logicalH } = await this.size();
@@ -1626,6 +1646,9 @@ const createPlatformActions = (device)=>({
1626
1646
  description: 'Execute ADB shell command on Android device',
1627
1647
  interfaceAlias: 'runAdbShell',
1628
1648
  paramSchema: runAdbShellParamSchema,
1649
+ sample: {
1650
+ command: 'dumpsys window displays | grep -E "mCurrentFocus"'
1651
+ },
1629
1652
  call: async (param)=>{
1630
1653
  if (!param.command || '' === param.command.trim()) throw new Error('RunAdbShell requires a non-empty command parameter');
1631
1654
  const adb = await device.getAdb();
@@ -1637,6 +1660,9 @@ const createPlatformActions = (device)=>({
1637
1660
  description: 'Launch an Android app or URL',
1638
1661
  interfaceAlias: 'launch',
1639
1662
  paramSchema: launchParamSchema,
1663
+ sample: {
1664
+ uri: 'com.example.app'
1665
+ },
1640
1666
  call: async (param)=>{
1641
1667
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
1642
1668
  await device.launch(param.uri);
@@ -705,6 +705,12 @@ class AndroidDevice {
705
705
  ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
706
706
  locate: getMidsceneLocationSchema().describe('The input field to be filled').optional()
707
707
  }),
708
+ sample: {
709
+ value: 'test@example.com',
710
+ locate: {
711
+ prompt: 'the email input field'
712
+ }
713
+ },
708
714
  call: async (param)=>{
709
715
  const element = param.locate;
710
716
  if ('typeOnly' !== param.mode) await this.clearInput(element);
@@ -772,6 +778,11 @@ class AndroidDevice {
772
778
  duration: z.number().optional().describe('The duration of the long press in milliseconds'),
773
779
  locate: getMidsceneLocationSchema().describe('The element to be long pressed')
774
780
  }),
781
+ sample: {
782
+ locate: {
783
+ prompt: 'the message bubble'
784
+ }
785
+ },
775
786
  call: async (param)=>{
776
787
  const element = param.locate;
777
788
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -791,6 +802,12 @@ class AndroidDevice {
791
802
  duration: z.number().optional().describe('The duration of the pull (in milliseconds)'),
792
803
  locate: getMidsceneLocationSchema().optional().describe('The element to start the pull from (optional)')
793
804
  }),
805
+ sample: {
806
+ direction: 'down',
807
+ locate: {
808
+ prompt: 'the center of the content list area'
809
+ }
810
+ },
794
811
  call: async (param)=>{
795
812
  const element = param.locate;
796
813
  const startPoint = element ? {
@@ -960,6 +977,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
960
977
  }
961
978
  async getScreenSize() {
962
979
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
980
+ debugDevice(`getScreenSize: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedSize=${!!this.cachedScreenSize}`);
963
981
  if (shouldCache && this.cachedScreenSize) return this.cachedScreenSize;
964
982
  const adb = await this.getAdb();
965
983
  if ('number' == typeof this.options?.displayId) try {
@@ -1093,6 +1111,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1093
1111
  }
1094
1112
  async getDisplayOrientation() {
1095
1113
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1114
+ debugDevice(`getDisplayOrientation: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedOrientation=${null !== this.cachedOrientation}`);
1096
1115
  if (shouldCache && null !== this.cachedOrientation) return this.cachedOrientation;
1097
1116
  const adb = await this.getAdb();
1098
1117
  let orientation = 0;
@@ -1137,6 +1156,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1137
1156
  }
1138
1157
  async getAdjustScale() {
1139
1158
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1159
+ debugDevice(`getAdjustScale: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedScale=${!!this.cachedAdjustScale}`);
1140
1160
  if (shouldCache && this.cachedAdjustScale) return this.cachedAdjustScale;
1141
1161
  const physical = await this.getOrientedPhysicalSize();
1142
1162
  const { width: logicalW, height: logicalH } = await this.size();
@@ -1722,6 +1742,9 @@ const createPlatformActions = (device)=>({
1722
1742
  description: 'Execute ADB shell command on Android device',
1723
1743
  interfaceAlias: 'runAdbShell',
1724
1744
  paramSchema: runAdbShellParamSchema,
1745
+ sample: {
1746
+ command: 'dumpsys window displays | grep -E "mCurrentFocus"'
1747
+ },
1725
1748
  call: async (param)=>{
1726
1749
  if (!param.command || '' === param.command.trim()) throw new Error('RunAdbShell requires a non-empty command parameter');
1727
1750
  const adb = await device.getAdb();
@@ -1733,6 +1756,9 @@ const createPlatformActions = (device)=>({
1733
1756
  description: 'Launch an Android app or URL',
1734
1757
  interfaceAlias: 'launch',
1735
1758
  paramSchema: launchParamSchema,
1759
+ sample: {
1760
+ uri: 'com.example.app'
1761
+ },
1736
1762
  call: async (param)=>{
1737
1763
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
1738
1764
  await device.launch(param.uri);
@@ -1885,7 +1911,7 @@ class AndroidMCPServer extends BaseMCPServer {
1885
1911
  constructor(toolsManager){
1886
1912
  super({
1887
1913
  name: '@midscene/android-mcp',
1888
- version: __VERSION__,
1914
+ version: "1.5.4",
1889
1915
  description: 'Control the Android device using natural language commands'
1890
1916
  }, toolsManager);
1891
1917
  }
package/dist/lib/cli.js CHANGED
@@ -721,6 +721,12 @@ var __webpack_exports__ = {};
721
721
  ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
722
722
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
723
723
  }),
724
+ sample: {
725
+ value: 'test@example.com',
726
+ locate: {
727
+ prompt: 'the email input field'
728
+ }
729
+ },
724
730
  call: async (param)=>{
725
731
  const element = param.locate;
726
732
  if ('typeOnly' !== param.mode) await this.clearInput(element);
@@ -788,6 +794,11 @@ var __webpack_exports__ = {};
788
794
  duration: core_namespaceObject.z.number().optional().describe('The duration of the long press in milliseconds'),
789
795
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The element to be long pressed')
790
796
  }),
797
+ sample: {
798
+ locate: {
799
+ prompt: 'the message bubble'
800
+ }
801
+ },
791
802
  call: async (param)=>{
792
803
  const element = param.locate;
793
804
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -807,6 +818,12 @@ var __webpack_exports__ = {};
807
818
  duration: core_namespaceObject.z.number().optional().describe('The duration of the pull (in milliseconds)'),
808
819
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().optional().describe('The element to start the pull from (optional)')
809
820
  }),
821
+ sample: {
822
+ direction: 'down',
823
+ locate: {
824
+ prompt: 'the center of the content list area'
825
+ }
826
+ },
810
827
  call: async (param)=>{
811
828
  const element = param.locate;
812
829
  const startPoint = element ? {
@@ -976,6 +993,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
976
993
  }
977
994
  async getScreenSize() {
978
995
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
996
+ debugDevice(`getScreenSize: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedSize=${!!this.cachedScreenSize}`);
979
997
  if (shouldCache && this.cachedScreenSize) return this.cachedScreenSize;
980
998
  const adb = await this.getAdb();
981
999
  if ('number' == typeof this.options?.displayId) try {
@@ -1109,6 +1127,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1109
1127
  }
1110
1128
  async getDisplayOrientation() {
1111
1129
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1130
+ debugDevice(`getDisplayOrientation: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedOrientation=${null !== this.cachedOrientation}`);
1112
1131
  if (shouldCache && null !== this.cachedOrientation) return this.cachedOrientation;
1113
1132
  const adb = await this.getAdb();
1114
1133
  let orientation = 0;
@@ -1153,6 +1172,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1153
1172
  }
1154
1173
  async getAdjustScale() {
1155
1174
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1175
+ debugDevice(`getAdjustScale: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedScale=${!!this.cachedAdjustScale}`);
1156
1176
  if (shouldCache && this.cachedAdjustScale) return this.cachedAdjustScale;
1157
1177
  const physical = await this.getOrientedPhysicalSize();
1158
1178
  const { width: logicalW, height: logicalH } = await this.size();
@@ -1738,6 +1758,9 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1738
1758
  description: 'Execute ADB shell command on Android device',
1739
1759
  interfaceAlias: 'runAdbShell',
1740
1760
  paramSchema: runAdbShellParamSchema,
1761
+ sample: {
1762
+ command: 'dumpsys window displays | grep -E "mCurrentFocus"'
1763
+ },
1741
1764
  call: async (param)=>{
1742
1765
  if (!param.command || '' === param.command.trim()) throw new Error('RunAdbShell requires a non-empty command parameter');
1743
1766
  const adb = await device.getAdb();
@@ -1749,6 +1772,9 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1749
1772
  description: 'Launch an Android app or URL',
1750
1773
  interfaceAlias: 'launch',
1751
1774
  paramSchema: launchParamSchema,
1775
+ sample: {
1776
+ uri: 'com.example.app'
1777
+ },
1752
1778
  call: async (param)=>{
1753
1779
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
1754
1780
  await device.launch(param.uri);
@@ -1896,7 +1922,8 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1896
1922
  }
1897
1923
  const tools = new AndroidMidsceneTools();
1898
1924
  (0, cli_namespaceObject.runToolsCLI)(tools, 'midscene-android', {
1899
- stripPrefix: 'android_'
1925
+ stripPrefix: 'android_',
1926
+ version: "1.5.4"
1900
1927
  }).catch((e)=>{
1901
1928
  if (!(e instanceof cli_namespaceObject.CLIError)) console.error(e);
1902
1929
  process.exit(e instanceof cli_namespaceObject.CLIError ? e.exitCode : 1);
package/dist/lib/index.js CHANGED
@@ -642,6 +642,12 @@ var __webpack_exports__ = {};
642
642
  ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
643
643
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
644
644
  }),
645
+ sample: {
646
+ value: 'test@example.com',
647
+ locate: {
648
+ prompt: 'the email input field'
649
+ }
650
+ },
645
651
  call: async (param)=>{
646
652
  const element = param.locate;
647
653
  if ('typeOnly' !== param.mode) await this.clearInput(element);
@@ -709,6 +715,11 @@ var __webpack_exports__ = {};
709
715
  duration: core_namespaceObject.z.number().optional().describe('The duration of the long press in milliseconds'),
710
716
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The element to be long pressed')
711
717
  }),
718
+ sample: {
719
+ locate: {
720
+ prompt: 'the message bubble'
721
+ }
722
+ },
712
723
  call: async (param)=>{
713
724
  const element = param.locate;
714
725
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -728,6 +739,12 @@ var __webpack_exports__ = {};
728
739
  duration: core_namespaceObject.z.number().optional().describe('The duration of the pull (in milliseconds)'),
729
740
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().optional().describe('The element to start the pull from (optional)')
730
741
  }),
742
+ sample: {
743
+ direction: 'down',
744
+ locate: {
745
+ prompt: 'the center of the content list area'
746
+ }
747
+ },
731
748
  call: async (param)=>{
732
749
  const element = param.locate;
733
750
  const startPoint = element ? {
@@ -897,6 +914,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
897
914
  }
898
915
  async getScreenSize() {
899
916
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
917
+ debugDevice(`getScreenSize: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedSize=${!!this.cachedScreenSize}`);
900
918
  if (shouldCache && this.cachedScreenSize) return this.cachedScreenSize;
901
919
  const adb = await this.getAdb();
902
920
  if ('number' == typeof this.options?.displayId) try {
@@ -1030,6 +1048,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1030
1048
  }
1031
1049
  async getDisplayOrientation() {
1032
1050
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1051
+ debugDevice(`getDisplayOrientation: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedOrientation=${null !== this.cachedOrientation}`);
1033
1052
  if (shouldCache && null !== this.cachedOrientation) return this.cachedOrientation;
1034
1053
  const adb = await this.getAdb();
1035
1054
  let orientation = 0;
@@ -1074,6 +1093,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1074
1093
  }
1075
1094
  async getAdjustScale() {
1076
1095
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1096
+ debugDevice(`getAdjustScale: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedScale=${!!this.cachedAdjustScale}`);
1077
1097
  if (shouldCache && this.cachedAdjustScale) return this.cachedAdjustScale;
1078
1098
  const physical = await this.getOrientedPhysicalSize();
1079
1099
  const { width: logicalW, height: logicalH } = await this.size();
@@ -1659,6 +1679,9 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1659
1679
  description: 'Execute ADB shell command on Android device',
1660
1680
  interfaceAlias: 'runAdbShell',
1661
1681
  paramSchema: runAdbShellParamSchema,
1682
+ sample: {
1683
+ command: 'dumpsys window displays | grep -E "mCurrentFocus"'
1684
+ },
1662
1685
  call: async (param)=>{
1663
1686
  if (!param.command || '' === param.command.trim()) throw new Error('RunAdbShell requires a non-empty command parameter');
1664
1687
  const adb = await device.getAdb();
@@ -1670,6 +1693,9 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1670
1693
  description: 'Launch an Android app or URL',
1671
1694
  interfaceAlias: 'launch',
1672
1695
  paramSchema: launchParamSchema,
1696
+ sample: {
1697
+ uri: 'com.example.app'
1698
+ },
1673
1699
  call: async (param)=>{
1674
1700
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
1675
1701
  await device.launch(param.uri);
@@ -736,6 +736,12 @@ var __webpack_exports__ = {};
736
736
  ]).default('replace').optional().describe('Input mode: "replace" (default) - clear the field and input the value; "typeOnly" - type the value directly without clearing the field first; "clear" - clear the field without inputting new text.')),
737
737
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The input field to be filled').optional()
738
738
  }),
739
+ sample: {
740
+ value: 'test@example.com',
741
+ locate: {
742
+ prompt: 'the email input field'
743
+ }
744
+ },
739
745
  call: async (param)=>{
740
746
  const element = param.locate;
741
747
  if ('typeOnly' !== param.mode) await this.clearInput(element);
@@ -803,6 +809,11 @@ var __webpack_exports__ = {};
803
809
  duration: core_namespaceObject.z.number().optional().describe('The duration of the long press in milliseconds'),
804
810
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().describe('The element to be long pressed')
805
811
  }),
812
+ sample: {
813
+ locate: {
814
+ prompt: 'the message bubble'
815
+ }
816
+ },
806
817
  call: async (param)=>{
807
818
  const element = param.locate;
808
819
  if (!element) throw new Error('LongPress requires an element to be located');
@@ -822,6 +833,12 @@ var __webpack_exports__ = {};
822
833
  duration: core_namespaceObject.z.number().optional().describe('The duration of the pull (in milliseconds)'),
823
834
  locate: (0, core_namespaceObject.getMidsceneLocationSchema)().optional().describe('The element to start the pull from (optional)')
824
835
  }),
836
+ sample: {
837
+ direction: 'down',
838
+ locate: {
839
+ prompt: 'the center of the content list area'
840
+ }
841
+ },
825
842
  call: async (param)=>{
826
843
  const element = param.locate;
827
844
  const startPoint = element ? {
@@ -991,6 +1008,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
991
1008
  }
992
1009
  async getScreenSize() {
993
1010
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1011
+ debugDevice(`getScreenSize: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedSize=${!!this.cachedScreenSize}`);
994
1012
  if (shouldCache && this.cachedScreenSize) return this.cachedScreenSize;
995
1013
  const adb = await this.getAdb();
996
1014
  if ('number' == typeof this.options?.displayId) try {
@@ -1124,6 +1142,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1124
1142
  }
1125
1143
  async getDisplayOrientation() {
1126
1144
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1145
+ debugDevice(`getDisplayOrientation: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedOrientation=${null !== this.cachedOrientation}`);
1127
1146
  if (shouldCache && null !== this.cachedOrientation) return this.cachedOrientation;
1128
1147
  const adb = await this.getAdb();
1129
1148
  let orientation = 0;
@@ -1168,6 +1187,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1168
1187
  }
1169
1188
  async getAdjustScale() {
1170
1189
  const shouldCache = !(this.options?.alwaysRefreshScreenInfo ?? false);
1190
+ debugDevice(`getAdjustScale: alwaysRefreshScreenInfo=${this.options?.alwaysRefreshScreenInfo}, shouldCache=${shouldCache}, hasCachedScale=${!!this.cachedAdjustScale}`);
1171
1191
  if (shouldCache && this.cachedAdjustScale) return this.cachedAdjustScale;
1172
1192
  const physical = await this.getOrientedPhysicalSize();
1173
1193
  const { width: logicalW, height: logicalH } = await this.size();
@@ -1753,6 +1773,9 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1753
1773
  description: 'Execute ADB shell command on Android device',
1754
1774
  interfaceAlias: 'runAdbShell',
1755
1775
  paramSchema: runAdbShellParamSchema,
1776
+ sample: {
1777
+ command: 'dumpsys window displays | grep -E "mCurrentFocus"'
1778
+ },
1756
1779
  call: async (param)=>{
1757
1780
  if (!param.command || '' === param.command.trim()) throw new Error('RunAdbShell requires a non-empty command parameter');
1758
1781
  const adb = await device.getAdb();
@@ -1764,6 +1787,9 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1764
1787
  description: 'Launch an Android app or URL',
1765
1788
  interfaceAlias: 'launch',
1766
1789
  paramSchema: launchParamSchema,
1790
+ sample: {
1791
+ uri: 'com.example.app'
1792
+ },
1767
1793
  call: async (param)=>{
1768
1794
  if (!param.uri || '' === param.uri.trim()) throw new Error('Launch requires a non-empty uri parameter');
1769
1795
  await device.launch(param.uri);
@@ -1916,7 +1942,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
1916
1942
  constructor(toolsManager){
1917
1943
  super({
1918
1944
  name: '@midscene/android-mcp',
1919
- version: __VERSION__,
1945
+ version: "1.5.4",
1920
1946
  description: 'Control the Android device using natural language commands'
1921
1947
  }, toolsManager);
1922
1948
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/android",
3
- "version": "1.5.4-beta-20260310030546.0",
3
+ "version": "1.5.4",
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": "^1.0.0",
42
42
  "appium-adb": "12.12.1",
43
43
  "sharp": "^0.34.3",
44
- "@midscene/core": "1.5.4-beta-20260310030546.0",
45
- "@midscene/shared": "1.5.4-beta-20260310030546.0"
44
+ "@midscene/core": "1.5.4",
45
+ "@midscene/shared": "1.5.4"
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.5.4-beta-20260310030546.0"
59
+ "@midscene/playground": "1.5.4"
60
60
  },
61
61
  "license": "MIT",
62
62
  "scripts": {