@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/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 typeText(text) {
258
+ async pasteText(text) {
258
259
  this.ensureSession();
260
+ const cleanText = text.trim();
261
+ if (!cleanText) return;
259
262
  try {
260
- const cleanText = text.trim();
261
- await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
262
- value: cleanText.split('')
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
- debugDevice(`Typing text: "${text}"`);
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 type text with WDA: ${error}`);
789
+ debugDevice(`Failed to input text with WDA: ${error}`);
734
790
  throw error;
735
791
  }
736
792
  if (shouldAutoDismissKeyboard) await this.hideKeyboard();
@@ -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 typeText(text) {
440
+ async pasteText(text) {
440
441
  this.ensureSession();
442
+ const cleanText = text.trim();
443
+ if (!cleanText) return;
441
444
  try {
442
- const cleanText = text.trim();
443
- await this.makeRequest('POST', `/session/${this.sessionId}/wda/keys`, {
444
- value: cleanText.split('')
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
- debugDevice(`Typing text: "${text}"`);
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 type text with WDA: ${error}`);
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.2",
1556
+ version: "1.9.3-beta-20260608113104.0",
1501
1557
  description: 'Control the iOS device using natural language commands'
1502
1558
  }, toolsManager);
1503
1559
  }
@@ -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
- typeText(text: string): Promise<void>;
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.2",
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.2",
52
- "@midscene/webdriver": "1.9.2",
53
- "@midscene/playground": "1.9.2",
54
- "@midscene/core": "1.9.2"
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.832f7e19.js"></script><link href="/static/css/index.bff8a97d.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
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>