@midscene/ios 1.9.2 → 1.9.3-beta-20260608113104.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/bin.mjs +64 -8
- package/dist/es/cli.mjs +65 -9
- package/dist/es/index.mjs +64 -8
- package/dist/es/mcp-server.mjs +65 -9
- package/dist/lib/bin.js +64 -8
- package/dist/lib/cli.js +65 -9
- package/dist/lib/index.js +64 -8
- package/dist/lib/mcp-server.js +65 -9
- package/dist/types/index.d.ts +6 -1
- package/package.json +5 -5
- package/static/index.html +1 -1
- package/static/static/js/{index.832f7e19.js → index.04a095cc.js} +15 -15
- package/static/static/js/index.04a095cc.js.map +1 -0
- package/static/static/js/index.832f7e19.js.map +0 -1
- /package/static/static/js/{index.832f7e19.js.LICENSE.txt → index.04a095cc.js.LICENSE.txt} +0 -0
package/dist/lib/index.js
CHANGED
|
@@ -56,6 +56,7 @@ const debugIOS = (0, logger_namespaceObject.getDebug)('webdriver:ios');
|
|
|
56
56
|
const WDA_MJPEG_SCREENSHOT_QUALITY = 50;
|
|
57
57
|
const WDA_MJPEG_FRAMERATE = 30;
|
|
58
58
|
const WDA_MJPEG_SCALING_FACTOR = 50;
|
|
59
|
+
const XCUI_KEY_MODIFIER_COMMAND = 16;
|
|
59
60
|
class IOSWebDriverClient extends webdriver_namespaceObject.WebDriverClient {
|
|
60
61
|
async launchApp(bundleId) {
|
|
61
62
|
this.ensureSession();
|
|
@@ -254,14 +255,57 @@ class IOSWebDriverClient extends webdriver_namespaceObject.WebDriverClient {
|
|
|
254
255
|
return false;
|
|
255
256
|
}
|
|
256
257
|
}
|
|
257
|
-
async
|
|
258
|
+
async pasteText(text) {
|
|
258
259
|
this.ensureSession();
|
|
260
|
+
const cleanText = text.trim();
|
|
261
|
+
if (!cleanText) return;
|
|
259
262
|
try {
|
|
260
|
-
|
|
261
|
-
await this.
|
|
262
|
-
|
|
263
|
+
await this.setPasteboardText(cleanText);
|
|
264
|
+
await this.sendPasteShortcut();
|
|
265
|
+
debugIOS(`Pasted text: "${text}"`);
|
|
266
|
+
} catch (error) {
|
|
267
|
+
debugIOS(`Failed to paste text "${text}": ${error}`);
|
|
268
|
+
throw new Error(`Failed to paste text: ${error}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
async setPasteboardText(text) {
|
|
272
|
+
this.ensureSession();
|
|
273
|
+
await this.makeRequest('POST', `/session/${this.sessionId}/wda/setPasteboard`, {
|
|
274
|
+
content: Buffer.from(text, 'utf8').toString('base64'),
|
|
275
|
+
contentType: 'plaintext'
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
async sendPasteShortcut() {
|
|
279
|
+
this.ensureSession();
|
|
280
|
+
const elementId = await this.getActiveElement() ?? '0';
|
|
281
|
+
await this.makeRequest('POST', `/session/${this.sessionId}/wda/element/${elementId}/keyboardInput`, {
|
|
282
|
+
keys: [
|
|
283
|
+
{
|
|
284
|
+
key: 'v',
|
|
285
|
+
modifierFlags: XCUI_KEY_MODIFIER_COMMAND
|
|
286
|
+
}
|
|
287
|
+
]
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
async typeText(text, options) {
|
|
291
|
+
this.ensureSession();
|
|
292
|
+
const cleanText = text.trim();
|
|
293
|
+
if (!cleanText) return;
|
|
294
|
+
const chars = Array.from(cleanText);
|
|
295
|
+
const delayMs = options?.delayMs ?? 0;
|
|
296
|
+
try {
|
|
297
|
+
if (delayMs > 0) for(let i = 0; i < chars.length; i++){
|
|
298
|
+
await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
|
|
299
|
+
value: [
|
|
300
|
+
chars[i]
|
|
301
|
+
]
|
|
302
|
+
});
|
|
303
|
+
if (i < chars.length - 1) await (0, utils_namespaceObject.sleep)(delayMs);
|
|
304
|
+
}
|
|
305
|
+
else await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
|
|
306
|
+
value: chars
|
|
263
307
|
});
|
|
264
|
-
debugIOS(`Typed text: "${text}"`);
|
|
308
|
+
debugIOS(`Typed text: "${text}" (delayMs=${delayMs})`);
|
|
265
309
|
} catch (error) {
|
|
266
310
|
debugIOS(`Failed to type text "${text}": ${error}`);
|
|
267
311
|
throw new Error(`Failed to type text: ${error}`);
|
|
@@ -724,13 +768,25 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
|
|
|
724
768
|
async typeText(text, options) {
|
|
725
769
|
if (!text) return;
|
|
726
770
|
const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
|
|
727
|
-
|
|
771
|
+
const delayMs = options?.keyboardTypeDelay ?? this.options?.keyboardTypeDelay ?? 80;
|
|
772
|
+
const keyboardInputStrategy = options?.keyboardInputStrategy ?? this.options?.keyboardInputStrategy ?? 'paste';
|
|
773
|
+
debugDevice(`Input text: "${text}" (strategy=${keyboardInputStrategy}, delayMs=${delayMs})`);
|
|
728
774
|
try {
|
|
729
775
|
await (0, utils_namespaceObject.sleep)(200);
|
|
730
|
-
await this.wdaBackend.typeText(text
|
|
776
|
+
if ('type' === keyboardInputStrategy) await this.wdaBackend.typeText(text, {
|
|
777
|
+
delayMs
|
|
778
|
+
});
|
|
779
|
+
else try {
|
|
780
|
+
await this.wdaBackend.pasteText(text);
|
|
781
|
+
} catch (pasteError) {
|
|
782
|
+
debugDevice(`Failed to paste text with WDA, falling back to typing: ${pasteError}`);
|
|
783
|
+
await this.wdaBackend.typeText(text, {
|
|
784
|
+
delayMs
|
|
785
|
+
});
|
|
786
|
+
}
|
|
731
787
|
await (0, utils_namespaceObject.sleep)(300);
|
|
732
788
|
} catch (error) {
|
|
733
|
-
debugDevice(`Failed to
|
|
789
|
+
debugDevice(`Failed to input text with WDA: ${error}`);
|
|
734
790
|
throw error;
|
|
735
791
|
}
|
|
736
792
|
if (shouldAutoDismissKeyboard) await this.hideKeyboard();
|
package/dist/lib/mcp-server.js
CHANGED
|
@@ -238,6 +238,7 @@ const debugIOS = (0, logger_namespaceObject.getDebug)('webdriver:ios');
|
|
|
238
238
|
const WDA_MJPEG_SCREENSHOT_QUALITY = 50;
|
|
239
239
|
const WDA_MJPEG_FRAMERATE = 30;
|
|
240
240
|
const WDA_MJPEG_SCALING_FACTOR = 50;
|
|
241
|
+
const XCUI_KEY_MODIFIER_COMMAND = 16;
|
|
241
242
|
class IOSWebDriverClient extends webdriver_namespaceObject.WebDriverClient {
|
|
242
243
|
async launchApp(bundleId) {
|
|
243
244
|
this.ensureSession();
|
|
@@ -436,14 +437,57 @@ class IOSWebDriverClient extends webdriver_namespaceObject.WebDriverClient {
|
|
|
436
437
|
return false;
|
|
437
438
|
}
|
|
438
439
|
}
|
|
439
|
-
async
|
|
440
|
+
async pasteText(text) {
|
|
440
441
|
this.ensureSession();
|
|
442
|
+
const cleanText = text.trim();
|
|
443
|
+
if (!cleanText) return;
|
|
441
444
|
try {
|
|
442
|
-
|
|
443
|
-
await this.
|
|
444
|
-
|
|
445
|
+
await this.setPasteboardText(cleanText);
|
|
446
|
+
await this.sendPasteShortcut();
|
|
447
|
+
debugIOS(`Pasted text: "${text}"`);
|
|
448
|
+
} catch (error) {
|
|
449
|
+
debugIOS(`Failed to paste text "${text}": ${error}`);
|
|
450
|
+
throw new Error(`Failed to paste text: ${error}`);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async setPasteboardText(text) {
|
|
454
|
+
this.ensureSession();
|
|
455
|
+
await this.makeRequest('POST', `/session/${this.sessionId}/wda/setPasteboard`, {
|
|
456
|
+
content: Buffer.from(text, 'utf8').toString('base64'),
|
|
457
|
+
contentType: 'plaintext'
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
async sendPasteShortcut() {
|
|
461
|
+
this.ensureSession();
|
|
462
|
+
const elementId = await this.getActiveElement() ?? '0';
|
|
463
|
+
await this.makeRequest('POST', `/session/${this.sessionId}/wda/element/${elementId}/keyboardInput`, {
|
|
464
|
+
keys: [
|
|
465
|
+
{
|
|
466
|
+
key: 'v',
|
|
467
|
+
modifierFlags: XCUI_KEY_MODIFIER_COMMAND
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
async typeText(text, options) {
|
|
473
|
+
this.ensureSession();
|
|
474
|
+
const cleanText = text.trim();
|
|
475
|
+
if (!cleanText) return;
|
|
476
|
+
const chars = Array.from(cleanText);
|
|
477
|
+
const delayMs = options?.delayMs ?? 0;
|
|
478
|
+
try {
|
|
479
|
+
if (delayMs > 0) for(let i = 0; i < chars.length; i++){
|
|
480
|
+
await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
|
|
481
|
+
value: [
|
|
482
|
+
chars[i]
|
|
483
|
+
]
|
|
484
|
+
});
|
|
485
|
+
if (i < chars.length - 1) await (0, core_utils_namespaceObject.sleep)(delayMs);
|
|
486
|
+
}
|
|
487
|
+
else await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
|
|
488
|
+
value: chars
|
|
445
489
|
});
|
|
446
|
-
debugIOS(`Typed text: "${text}"`);
|
|
490
|
+
debugIOS(`Typed text: "${text}" (delayMs=${delayMs})`);
|
|
447
491
|
} catch (error) {
|
|
448
492
|
debugIOS(`Failed to type text "${text}": ${error}`);
|
|
449
493
|
throw new Error(`Failed to type text: ${error}`);
|
|
@@ -906,13 +950,25 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
|
|
|
906
950
|
async typeText(text, options) {
|
|
907
951
|
if (!text) return;
|
|
908
952
|
const shouldAutoDismissKeyboard = options?.autoDismissKeyboard ?? this.options?.autoDismissKeyboard ?? true;
|
|
909
|
-
|
|
953
|
+
const delayMs = options?.keyboardTypeDelay ?? this.options?.keyboardTypeDelay ?? 80;
|
|
954
|
+
const keyboardInputStrategy = options?.keyboardInputStrategy ?? this.options?.keyboardInputStrategy ?? 'paste';
|
|
955
|
+
debugDevice(`Input text: "${text}" (strategy=${keyboardInputStrategy}, delayMs=${delayMs})`);
|
|
910
956
|
try {
|
|
911
957
|
await (0, core_utils_namespaceObject.sleep)(200);
|
|
912
|
-
await this.wdaBackend.typeText(text
|
|
958
|
+
if ('type' === keyboardInputStrategy) await this.wdaBackend.typeText(text, {
|
|
959
|
+
delayMs
|
|
960
|
+
});
|
|
961
|
+
else try {
|
|
962
|
+
await this.wdaBackend.pasteText(text);
|
|
963
|
+
} catch (pasteError) {
|
|
964
|
+
debugDevice(`Failed to paste text with WDA, falling back to typing: ${pasteError}`);
|
|
965
|
+
await this.wdaBackend.typeText(text, {
|
|
966
|
+
delayMs
|
|
967
|
+
});
|
|
968
|
+
}
|
|
913
969
|
await (0, core_utils_namespaceObject.sleep)(300);
|
|
914
970
|
} catch (error) {
|
|
915
|
-
debugDevice(`Failed to
|
|
971
|
+
debugDevice(`Failed to input text with WDA: ${error}`);
|
|
916
972
|
throw error;
|
|
917
973
|
}
|
|
918
974
|
if (shouldAutoDismissKeyboard) await this.hideKeyboard();
|
|
@@ -1497,7 +1553,7 @@ class IOSMCPServer extends mcp_namespaceObject.BaseMCPServer {
|
|
|
1497
1553
|
constructor(toolsManager){
|
|
1498
1554
|
super({
|
|
1499
1555
|
name: '@midscene/ios-mcp',
|
|
1500
|
-
version: "1.9.
|
|
1556
|
+
version: "1.9.3-beta-20260608113104.0",
|
|
1501
1557
|
description: 'Control the iOS device using natural language commands'
|
|
1502
1558
|
}, toolsManager);
|
|
1503
1559
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -227,7 +227,12 @@ export declare class IOSWebDriverClient extends WebDriverClient {
|
|
|
227
227
|
clearActiveElement(): Promise<boolean>;
|
|
228
228
|
private normalizeKeyName;
|
|
229
229
|
dismissKeyboard(keyNames?: string[]): Promise<boolean>;
|
|
230
|
-
|
|
230
|
+
pasteText(text: string): Promise<void>;
|
|
231
|
+
private setPasteboardText;
|
|
232
|
+
private sendPasteShortcut;
|
|
233
|
+
typeText(text: string, options?: {
|
|
234
|
+
delayMs?: number;
|
|
235
|
+
}): Promise<void>;
|
|
231
236
|
tap(x: number, y: number): Promise<void>;
|
|
232
237
|
swipe(fromX: number, fromY: number, toX: number, toY: number, duration?: number): Promise<void>;
|
|
233
238
|
pinch(centerX: number, centerY: number, startDistance: number, endDistance: number, duration?: number): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@midscene/ios",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.3-beta-20260608113104.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/web-infra-dev/midscene.git",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@inquirer/prompts": "^7.8.6",
|
|
50
50
|
"open": "10.1.0",
|
|
51
|
-
"@midscene/shared": "1.9.
|
|
52
|
-
"@midscene/
|
|
53
|
-
"@midscene/
|
|
54
|
-
"@midscene/
|
|
51
|
+
"@midscene/shared": "1.9.3-beta-20260608113104.0",
|
|
52
|
+
"@midscene/core": "1.9.3-beta-20260608113104.0",
|
|
53
|
+
"@midscene/webdriver": "1.9.3-beta-20260608113104.0",
|
|
54
|
+
"@midscene/playground": "1.9.3-beta-20260608113104.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@rslib/core": "^0.18.3",
|
package/static/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html><head><link rel="icon" href="/favicon.ico"><title>Midscene Playground</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/static/js/lib-react.7b1abe58.js"></script><script defer src="/static/js/596.5426be9e.js"></script><script defer src="/static/js/index.
|
|
1
|
+
<!doctype html><html><head><link rel="icon" href="/favicon.ico"><title>Midscene Playground</title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><script defer src="/static/js/lib-react.7b1abe58.js"></script><script defer src="/static/js/596.5426be9e.js"></script><script defer src="/static/js/index.04a095cc.js"></script><link href="/static/css/index.bff8a97d.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
|