@midscene/android 1.3.11 → 1.3.12-beta-20260211080855.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/index.mjs +14 -7
- package/dist/es/mcp-server.mjs +14 -7
- package/dist/lib/index.js +14 -7
- package/dist/lib/mcp-server.js +14 -7
- package/dist/types/index.d.ts +9 -6
- package/dist/types/mcp-server.d.ts +9 -6
- package/package.json +4 -4
package/dist/es/index.mjs
CHANGED
|
@@ -556,7 +556,7 @@ const IME_STRATEGY_ALWAYS_YADB = 'always-yadb';
|
|
|
556
556
|
const IME_STRATEGY_YADB_FOR_NON_ASCII = 'yadb-for-non-ascii';
|
|
557
557
|
const debugDevice = (0, logger_.getDebug)('android:device');
|
|
558
558
|
function escapeForShell(text) {
|
|
559
|
-
return text.replace(
|
|
559
|
+
return text.replace(/'/g, "'\\''").replace(/\n/g, '\\n');
|
|
560
560
|
}
|
|
561
561
|
class AndroidDevice {
|
|
562
562
|
actionSpace() {
|
|
@@ -827,7 +827,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
827
827
|
async execYadb(keyboardContent) {
|
|
828
828
|
await this.ensureYadb();
|
|
829
829
|
const adb = await this.getAdb();
|
|
830
|
-
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard
|
|
830
|
+
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard '${keyboardContent}'`);
|
|
831
831
|
}
|
|
832
832
|
async getElementsInfo() {
|
|
833
833
|
return [];
|
|
@@ -1275,17 +1275,24 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
1275
1275
|
shouldUseYadbForText(text) {
|
|
1276
1276
|
const hasNonAscii = /[\x80-\uFFFF]/.test(text);
|
|
1277
1277
|
const hasFormatSpecifiers = /%[a-zA-Z]/.test(text);
|
|
1278
|
-
|
|
1278
|
+
const hasShellSpecialChars = /[\\`$]/.test(text);
|
|
1279
|
+
const hasBothQuotes = text.includes('"') && text.includes("'");
|
|
1280
|
+
return hasNonAscii || hasFormatSpecifiers || hasShellSpecialChars || hasBothQuotes;
|
|
1279
1281
|
}
|
|
1280
1282
|
async keyboardType(text, options) {
|
|
1281
1283
|
if (!text) return;
|
|
1282
1284
|
const adb = await this.getAdb();
|
|
1283
|
-
const shouldUseYadb = this.shouldUseYadbForText(text);
|
|
1284
1285
|
const IME_STRATEGY = (this.options?.imeStrategy || globalConfigManager.getEnvConfigValue(MIDSCENE_ANDROID_IME_STRATEGY)) ?? IME_STRATEGY_YADB_FOR_NON_ASCII;
|
|
1285
1286
|
const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
|
|
1286
|
-
const
|
|
1287
|
-
if (
|
|
1288
|
-
else
|
|
1287
|
+
const useYadb = IME_STRATEGY === IME_STRATEGY_ALWAYS_YADB || IME_STRATEGY === IME_STRATEGY_YADB_FOR_NON_ASCII && this.shouldUseYadbForText(text);
|
|
1288
|
+
if (useYadb) await this.execYadb(escapeForShell(text));
|
|
1289
|
+
else {
|
|
1290
|
+
const segments = text.split('\n');
|
|
1291
|
+
for(let i = 0; i < segments.length; i++){
|
|
1292
|
+
if (segments[i].length > 0) await adb.inputText(segments[i]);
|
|
1293
|
+
if (i < segments.length - 1) await adb.keyevent(66);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1289
1296
|
if (true === shouldAutoDismissKeyboard) await this.hideKeyboard(options);
|
|
1290
1297
|
}
|
|
1291
1298
|
normalizeKeyName(key) {
|
package/dist/es/mcp-server.mjs
CHANGED
|
@@ -653,7 +653,7 @@ const IME_STRATEGY_ALWAYS_YADB = 'always-yadb';
|
|
|
653
653
|
const IME_STRATEGY_YADB_FOR_NON_ASCII = 'yadb-for-non-ascii';
|
|
654
654
|
const debugDevice = (0, logger_.getDebug)('android:device');
|
|
655
655
|
function escapeForShell(text) {
|
|
656
|
-
return text.replace(
|
|
656
|
+
return text.replace(/'/g, "'\\''").replace(/\n/g, '\\n');
|
|
657
657
|
}
|
|
658
658
|
class AndroidDevice {
|
|
659
659
|
actionSpace() {
|
|
@@ -924,7 +924,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
924
924
|
async execYadb(keyboardContent) {
|
|
925
925
|
await this.ensureYadb();
|
|
926
926
|
const adb = await this.getAdb();
|
|
927
|
-
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard
|
|
927
|
+
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard '${keyboardContent}'`);
|
|
928
928
|
}
|
|
929
929
|
async getElementsInfo() {
|
|
930
930
|
return [];
|
|
@@ -1372,17 +1372,24 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
1372
1372
|
shouldUseYadbForText(text) {
|
|
1373
1373
|
const hasNonAscii = /[\x80-\uFFFF]/.test(text);
|
|
1374
1374
|
const hasFormatSpecifiers = /%[a-zA-Z]/.test(text);
|
|
1375
|
-
|
|
1375
|
+
const hasShellSpecialChars = /[\\`$]/.test(text);
|
|
1376
|
+
const hasBothQuotes = text.includes('"') && text.includes("'");
|
|
1377
|
+
return hasNonAscii || hasFormatSpecifiers || hasShellSpecialChars || hasBothQuotes;
|
|
1376
1378
|
}
|
|
1377
1379
|
async keyboardType(text, options) {
|
|
1378
1380
|
if (!text) return;
|
|
1379
1381
|
const adb = await this.getAdb();
|
|
1380
|
-
const shouldUseYadb = this.shouldUseYadbForText(text);
|
|
1381
1382
|
const IME_STRATEGY = (this.options?.imeStrategy || globalConfigManager.getEnvConfigValue(MIDSCENE_ANDROID_IME_STRATEGY)) ?? IME_STRATEGY_YADB_FOR_NON_ASCII;
|
|
1382
1383
|
const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
|
|
1383
|
-
const
|
|
1384
|
-
if (
|
|
1385
|
-
else
|
|
1384
|
+
const useYadb = IME_STRATEGY === IME_STRATEGY_ALWAYS_YADB || IME_STRATEGY === IME_STRATEGY_YADB_FOR_NON_ASCII && this.shouldUseYadbForText(text);
|
|
1385
|
+
if (useYadb) await this.execYadb(escapeForShell(text));
|
|
1386
|
+
else {
|
|
1387
|
+
const segments = text.split('\n');
|
|
1388
|
+
for(let i = 0; i < segments.length; i++){
|
|
1389
|
+
if (segments[i].length > 0) await adb.inputText(segments[i]);
|
|
1390
|
+
if (i < segments.length - 1) await adb.keyevent(66);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1386
1393
|
if (true === shouldAutoDismissKeyboard) await this.hideKeyboard(options);
|
|
1387
1394
|
}
|
|
1388
1395
|
normalizeKeyName(key) {
|
package/dist/lib/index.js
CHANGED
|
@@ -589,7 +589,7 @@ var __webpack_exports__ = {};
|
|
|
589
589
|
const IME_STRATEGY_YADB_FOR_NON_ASCII = 'yadb-for-non-ascii';
|
|
590
590
|
const debugDevice = (0, logger_.getDebug)('android:device');
|
|
591
591
|
function escapeForShell(text) {
|
|
592
|
-
return text.replace(
|
|
592
|
+
return text.replace(/'/g, "'\\''").replace(/\n/g, '\\n');
|
|
593
593
|
}
|
|
594
594
|
class AndroidDevice {
|
|
595
595
|
actionSpace() {
|
|
@@ -860,7 +860,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
860
860
|
async execYadb(keyboardContent) {
|
|
861
861
|
await this.ensureYadb();
|
|
862
862
|
const adb = await this.getAdb();
|
|
863
|
-
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard
|
|
863
|
+
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard '${keyboardContent}'`);
|
|
864
864
|
}
|
|
865
865
|
async getElementsInfo() {
|
|
866
866
|
return [];
|
|
@@ -1308,17 +1308,24 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
1308
1308
|
shouldUseYadbForText(text) {
|
|
1309
1309
|
const hasNonAscii = /[\x80-\uFFFF]/.test(text);
|
|
1310
1310
|
const hasFormatSpecifiers = /%[a-zA-Z]/.test(text);
|
|
1311
|
-
|
|
1311
|
+
const hasShellSpecialChars = /[\\`$]/.test(text);
|
|
1312
|
+
const hasBothQuotes = text.includes('"') && text.includes("'");
|
|
1313
|
+
return hasNonAscii || hasFormatSpecifiers || hasShellSpecialChars || hasBothQuotes;
|
|
1312
1314
|
}
|
|
1313
1315
|
async keyboardType(text, options) {
|
|
1314
1316
|
if (!text) return;
|
|
1315
1317
|
const adb = await this.getAdb();
|
|
1316
|
-
const shouldUseYadb = this.shouldUseYadbForText(text);
|
|
1317
1318
|
const IME_STRATEGY = (this.options?.imeStrategy || env_namespaceObject.globalConfigManager.getEnvConfigValue(env_namespaceObject.MIDSCENE_ANDROID_IME_STRATEGY)) ?? IME_STRATEGY_YADB_FOR_NON_ASCII;
|
|
1318
1319
|
const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
|
|
1319
|
-
const
|
|
1320
|
-
if (
|
|
1321
|
-
else
|
|
1320
|
+
const useYadb = IME_STRATEGY === IME_STRATEGY_ALWAYS_YADB || IME_STRATEGY === IME_STRATEGY_YADB_FOR_NON_ASCII && this.shouldUseYadbForText(text);
|
|
1321
|
+
if (useYadb) await this.execYadb(escapeForShell(text));
|
|
1322
|
+
else {
|
|
1323
|
+
const segments = text.split('\n');
|
|
1324
|
+
for(let i = 0; i < segments.length; i++){
|
|
1325
|
+
if (segments[i].length > 0) await adb.inputText(segments[i]);
|
|
1326
|
+
if (i < segments.length - 1) await adb.keyevent(66);
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1322
1329
|
if (true === shouldAutoDismissKeyboard) await this.hideKeyboard(options);
|
|
1323
1330
|
}
|
|
1324
1331
|
normalizeKeyName(key) {
|
package/dist/lib/mcp-server.js
CHANGED
|
@@ -684,7 +684,7 @@ var __webpack_exports__ = {};
|
|
|
684
684
|
const IME_STRATEGY_YADB_FOR_NON_ASCII = 'yadb-for-non-ascii';
|
|
685
685
|
const debugDevice = (0, logger_.getDebug)('android:device');
|
|
686
686
|
function escapeForShell(text) {
|
|
687
|
-
return text.replace(
|
|
687
|
+
return text.replace(/'/g, "'\\''").replace(/\n/g, '\\n');
|
|
688
688
|
}
|
|
689
689
|
class AndroidDevice {
|
|
690
690
|
actionSpace() {
|
|
@@ -955,7 +955,7 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
955
955
|
async execYadb(keyboardContent) {
|
|
956
956
|
await this.ensureYadb();
|
|
957
957
|
const adb = await this.getAdb();
|
|
958
|
-
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard
|
|
958
|
+
await adb.shell(`app_process${this.getDisplayArg()} -Djava.class.path=/data/local/tmp/yadb /data/local/tmp com.ysbing.yadb.Main -keyboard '${keyboardContent}'`);
|
|
959
959
|
}
|
|
960
960
|
async getElementsInfo() {
|
|
961
961
|
return [];
|
|
@@ -1403,17 +1403,24 @@ ${Object.keys(size).filter((key)=>size[key]).map((key)=>` ${key} size: ${size[k
|
|
|
1403
1403
|
shouldUseYadbForText(text) {
|
|
1404
1404
|
const hasNonAscii = /[\x80-\uFFFF]/.test(text);
|
|
1405
1405
|
const hasFormatSpecifiers = /%[a-zA-Z]/.test(text);
|
|
1406
|
-
|
|
1406
|
+
const hasShellSpecialChars = /[\\`$]/.test(text);
|
|
1407
|
+
const hasBothQuotes = text.includes('"') && text.includes("'");
|
|
1408
|
+
return hasNonAscii || hasFormatSpecifiers || hasShellSpecialChars || hasBothQuotes;
|
|
1407
1409
|
}
|
|
1408
1410
|
async keyboardType(text, options) {
|
|
1409
1411
|
if (!text) return;
|
|
1410
1412
|
const adb = await this.getAdb();
|
|
1411
|
-
const shouldUseYadb = this.shouldUseYadbForText(text);
|
|
1412
1413
|
const IME_STRATEGY = (this.options?.imeStrategy || env_namespaceObject.globalConfigManager.getEnvConfigValue(env_namespaceObject.MIDSCENE_ANDROID_IME_STRATEGY)) ?? IME_STRATEGY_YADB_FOR_NON_ASCII;
|
|
1413
1414
|
const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
|
|
1414
|
-
const
|
|
1415
|
-
if (
|
|
1416
|
-
else
|
|
1415
|
+
const useYadb = IME_STRATEGY === IME_STRATEGY_ALWAYS_YADB || IME_STRATEGY === IME_STRATEGY_YADB_FOR_NON_ASCII && this.shouldUseYadbForText(text);
|
|
1416
|
+
if (useYadb) await this.execYadb(escapeForShell(text));
|
|
1417
|
+
else {
|
|
1418
|
+
const segments = text.split('\n');
|
|
1419
|
+
for(let i = 0; i < segments.length; i++){
|
|
1420
|
+
if (segments[i].length > 0) await adb.inputText(segments[i]);
|
|
1421
|
+
if (i < segments.length - 1) await adb.keyevent(66);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1417
1424
|
if (true === shouldAutoDismissKeyboard) await this.hideKeyboard(options);
|
|
1418
1425
|
}
|
|
1419
1426
|
normalizeKeyName(key) {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -144,12 +144,15 @@ export declare class AndroidDevice implements AbstractInterface {
|
|
|
144
144
|
scrollRight(distance?: number, startPoint?: Point): Promise<void>;
|
|
145
145
|
ensureYadb(): Promise<void>;
|
|
146
146
|
/**
|
|
147
|
-
* Check if text contains characters that may cause issues with ADB inputText
|
|
148
|
-
*
|
|
149
|
-
* -
|
|
150
|
-
* -
|
|
151
|
-
* -
|
|
152
|
-
* -
|
|
147
|
+
* Check if text contains characters that may cause issues with ADB inputText.
|
|
148
|
+
* appium-adb's inputText has known bugs with certain characters:
|
|
149
|
+
* - Backslash causes broken shell quoting
|
|
150
|
+
* - Backtick is not escaped at all
|
|
151
|
+
* - Text containing both " and ' throws an error
|
|
152
|
+
* - Dollar sign can cause variable expansion issues
|
|
153
|
+
*
|
|
154
|
+
* For these characters, we route through yadb which handles them correctly
|
|
155
|
+
* via escapeForShell + double-quoted shell context.
|
|
153
156
|
*/
|
|
154
157
|
private shouldUseYadbForText;
|
|
155
158
|
keyboardType(text: string, options?: AndroidDeviceInputOpt): Promise<void>;
|
|
@@ -145,12 +145,15 @@ declare class AndroidDevice implements AbstractInterface {
|
|
|
145
145
|
scrollRight(distance?: number, startPoint?: Point): Promise<void>;
|
|
146
146
|
ensureYadb(): Promise<void>;
|
|
147
147
|
/**
|
|
148
|
-
* Check if text contains characters that may cause issues with ADB inputText
|
|
149
|
-
*
|
|
150
|
-
* -
|
|
151
|
-
* -
|
|
152
|
-
* -
|
|
153
|
-
* -
|
|
148
|
+
* Check if text contains characters that may cause issues with ADB inputText.
|
|
149
|
+
* appium-adb's inputText has known bugs with certain characters:
|
|
150
|
+
* - Backslash causes broken shell quoting
|
|
151
|
+
* - Backtick is not escaped at all
|
|
152
|
+
* - Text containing both " and ' throws an error
|
|
153
|
+
* - Dollar sign can cause variable expansion issues
|
|
154
|
+
*
|
|
155
|
+
* For these characters, we route through yadb which handles them correctly
|
|
156
|
+
* via escapeForShell + double-quoted shell context.
|
|
154
157
|
*/
|
|
155
158
|
private shouldUseYadbForText;
|
|
156
159
|
keyboardType(text: string, options?: AndroidDeviceInputOpt): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midscene/android",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.12-beta-20260211080855.0",
|
|
4
4
|
"description": "Android automation library for Midscene",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Android UI automation",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"@yume-chan/stream-extra": "^1.0.0",
|
|
39
39
|
"appium-adb": "12.12.1",
|
|
40
40
|
"sharp": "^0.34.3",
|
|
41
|
-
"@midscene/
|
|
42
|
-
"@midscene/
|
|
41
|
+
"@midscene/core": "1.3.12-beta-20260211080855.0",
|
|
42
|
+
"@midscene/shared": "1.3.12-beta-20260211080855.0"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
45
|
"@ffmpeg-installer/ffmpeg": "^1.1.0"
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"tsx": "^4.19.2",
|
|
54
54
|
"vitest": "3.0.5",
|
|
55
55
|
"zod": "3.24.3",
|
|
56
|
-
"@midscene/playground": "1.3.
|
|
56
|
+
"@midscene/playground": "1.3.12-beta-20260211080855.0"
|
|
57
57
|
},
|
|
58
58
|
"license": "MIT",
|
|
59
59
|
"scripts": {
|