@midscene/ios 0.30.6-beta-20251022112352.0 → 0.30.6-beta-20251023082056.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/bin.js CHANGED
@@ -11649,8 +11649,8 @@ var __webpack_exports__ = {};
11649
11649
  }));
11650
11650
  this._app.use((req, _res, next)=>{
11651
11651
  const { context } = req.body || {};
11652
- if (context && 'updateContext' in this.page && 'function' == typeof this.page.updateContext) {
11653
- this.page.updateContext(context);
11652
+ if (context && 'updateContext' in this.agent.interface && 'function' == typeof this.agent.interface.updateContext) {
11653
+ this.agent.interface.updateContext(context);
11654
11654
  console.log('Context updated by PlaygroundServer middleware');
11655
11655
  }
11656
11656
  next();
@@ -11669,6 +11669,22 @@ var __webpack_exports__ = {};
11669
11669
  (0, external_node_fs_namespaceObject.writeFileSync)(tmpFile, context);
11670
11670
  return tmpFile;
11671
11671
  }
11672
+ async recreateAgent() {
11673
+ if (!this.agentFactory) return void console.warn('Cannot recreate agent: factory function not provided. Agent recreation is only available when using factory mode.');
11674
+ console.log('Recreating agent to cancel current task...');
11675
+ try {
11676
+ if (this.agent && 'function' == typeof this.agent.destroy) await this.agent.destroy();
11677
+ } catch (error) {
11678
+ console.warn('Failed to destroy old agent:', error);
11679
+ }
11680
+ try {
11681
+ this.agent = await this.agentFactory();
11682
+ console.log('Agent recreated successfully');
11683
+ } catch (error) {
11684
+ console.error('Failed to recreate agent:', error);
11685
+ throw error;
11686
+ }
11687
+ }
11672
11688
  setupRoutes() {
11673
11689
  this._app.get('/status', async (req, res)=>{
11674
11690
  res.send({
@@ -11696,7 +11712,7 @@ var __webpack_exports__ = {};
11696
11712
  this._app.post('/action-space', async (req, res)=>{
11697
11713
  try {
11698
11714
  let actionSpace = [];
11699
- actionSpace = await this.page.actionSpace();
11715
+ actionSpace = await this.agent.interface.actionSpace();
11700
11716
  const processedActionSpace = actionSpace.map((action)=>{
11701
11717
  if (action && 'object' == typeof action && 'paramSchema' in action) {
11702
11718
  const typedAction = action;
@@ -11745,7 +11761,12 @@ var __webpack_exports__ = {};
11745
11761
  if (!type) return res.status(400).json({
11746
11762
  error: 'type is required'
11747
11763
  });
11764
+ if (this.currentTaskId) return res.status(409).json({
11765
+ error: 'Another task is already running',
11766
+ currentTaskId: this.currentTaskId
11767
+ });
11748
11768
  if (requestId) {
11769
+ this.currentTaskId = requestId;
11749
11770
  this.taskProgressTips[requestId] = '';
11750
11771
  this.agent.onTaskStartTip = (tip)=>{
11751
11772
  this.taskProgressTips[requestId] = tip;
@@ -11760,7 +11781,7 @@ var __webpack_exports__ = {};
11760
11781
  };
11761
11782
  const startTime = Date.now();
11762
11783
  try {
11763
- const actionSpace = await this.page.actionSpace();
11784
+ const actionSpace = await this.agent.interface.actionSpace();
11764
11785
  const value = {
11765
11786
  type,
11766
11787
  prompt,
@@ -11787,7 +11808,10 @@ var __webpack_exports__ = {};
11787
11808
  const timeCost = Date.now() - startTime;
11788
11809
  if (response.error) console.error(`handle request failed after ${timeCost}ms: requestId: ${requestId}, ${response.error}`);
11789
11810
  else console.log(`handle request done after ${timeCost}ms: requestId: ${requestId}`);
11790
- if (requestId) delete this.taskProgressTips[requestId];
11811
+ if (requestId) {
11812
+ delete this.taskProgressTips[requestId];
11813
+ if (this.currentTaskId === requestId) this.currentTaskId = null;
11814
+ }
11791
11815
  });
11792
11816
  this._app.post('/cancel/:requestId', async (req, res)=>{
11793
11817
  const { requestId } = req.params;
@@ -11795,9 +11819,17 @@ var __webpack_exports__ = {};
11795
11819
  error: 'requestId is required'
11796
11820
  });
11797
11821
  try {
11798
- if (this.taskProgressTips[requestId]) delete this.taskProgressTips[requestId];
11822
+ if (this.currentTaskId !== requestId) return res.json({
11823
+ status: 'not_found',
11824
+ message: 'Task not found or already completed'
11825
+ });
11826
+ console.log(`Cancelling task: ${requestId}`);
11827
+ await this.recreateAgent();
11828
+ delete this.taskProgressTips[requestId];
11829
+ this.currentTaskId = null;
11799
11830
  res.json({
11800
- status: 'cancelled'
11831
+ status: 'cancelled',
11832
+ message: 'Task cancelled successfully by recreating agent'
11801
11833
  });
11802
11834
  } catch (error) {
11803
11835
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
@@ -11809,10 +11841,10 @@ var __webpack_exports__ = {};
11809
11841
  });
11810
11842
  this._app.get('/screenshot', async (_req, res)=>{
11811
11843
  try {
11812
- if ('function' != typeof this.page.screenshotBase64) return res.status(500).json({
11844
+ if ('function' != typeof this.agent.interface.screenshotBase64) return res.status(500).json({
11813
11845
  error: 'Screenshot method not available on current interface'
11814
11846
  });
11815
- const base64Screenshot = await this.page.screenshotBase64();
11847
+ const base64Screenshot = await this.agent.interface.screenshotBase64();
11816
11848
  res.json({
11817
11849
  screenshot: base64Screenshot,
11818
11850
  timestamp: Date.now()
@@ -11827,9 +11859,9 @@ var __webpack_exports__ = {};
11827
11859
  });
11828
11860
  this._app.get('/interface-info', async (_req, res)=>{
11829
11861
  try {
11830
- var _this_page_describe, _this_page;
11831
- const type = this.page.interfaceType || 'Unknown';
11832
- const description = (null == (_this_page_describe = (_this_page = this.page).describe) ? void 0 : _this_page_describe.call(_this_page)) || void 0;
11862
+ var _this_agent_interface_describe, _this_agent_interface;
11863
+ const type = this.agent.interface.interfaceType || 'Unknown';
11864
+ const description = (null == (_this_agent_interface_describe = (_this_agent_interface = this.agent.interface).describe) ? void 0 : _this_agent_interface_describe.call(_this_agent_interface)) || void 0;
11833
11865
  res.json({
11834
11866
  type,
11835
11867
  description
@@ -11897,6 +11929,11 @@ var __webpack_exports__ = {};
11897
11929
  }
11898
11930
  }
11899
11931
  async launch(port) {
11932
+ if (this.agentFactory) {
11933
+ console.log('Initializing agent from factory function...');
11934
+ this.agent = await this.agentFactory();
11935
+ console.log('Agent initialized successfully');
11936
+ }
11900
11937
  this.initializeApp();
11901
11938
  this.port = port || defaultPort;
11902
11939
  return new Promise((resolve)=>{
@@ -11925,24 +11962,30 @@ var __webpack_exports__ = {};
11925
11962
  } else resolve();
11926
11963
  });
11927
11964
  }
11928
- constructor(page, agent, staticPath = STATIC_PATH, id){
11965
+ constructor(agent, staticPath = STATIC_PATH, id){
11929
11966
  _define_property(this, "_app", void 0);
11930
11967
  _define_property(this, "tmpDir", void 0);
11931
11968
  _define_property(this, "server", void 0);
11932
11969
  _define_property(this, "port", void 0);
11933
- _define_property(this, "page", void 0);
11934
11970
  _define_property(this, "agent", void 0);
11935
11971
  _define_property(this, "staticPath", void 0);
11936
11972
  _define_property(this, "taskProgressTips", void 0);
11937
11973
  _define_property(this, "id", void 0);
11938
11974
  _define_property(this, "_initialized", false);
11975
+ _define_property(this, "agentFactory", void 0);
11976
+ _define_property(this, "currentTaskId", null);
11939
11977
  this._app = express_default()();
11940
11978
  this.tmpDir = (0, utils_namespaceObject.getTmpDir)();
11941
- this.page = page;
11942
- this.agent = agent;
11943
11979
  this.staticPath = staticPath;
11944
11980
  this.taskProgressTips = {};
11945
11981
  this.id = id || (0, shared_utils_namespaceObject.uuid)();
11982
+ if ('function' == typeof agent) {
11983
+ this.agentFactory = agent;
11984
+ this.agent = null;
11985
+ } else {
11986
+ this.agent = agent;
11987
+ this.agentFactory = null;
11988
+ }
11946
11989
  }
11947
11990
  }
11948
11991
  const external_node_child_process_namespaceObject = require("node:child_process");
@@ -12140,19 +12183,45 @@ var __webpack_exports__ = {};
12140
12183
  }
12141
12184
  async swipe(fromX, fromY, toX, toY, duration = 500) {
12142
12185
  this.ensureSession();
12143
- try {
12144
- await this.makeRequest('POST', `/session/${this.sessionId}/wda/dragfromtoforduration`, {
12145
- fromX,
12146
- fromY,
12147
- toX,
12148
- toY,
12149
- duration: duration / 1000
12150
- });
12151
- debugIOS(`Swiped from (${fromX}, ${fromY}) to (${toX}, ${toY}) in ${duration}ms`);
12152
- } catch (error) {
12153
- debugIOS(`Failed to swipe from (${fromX}, ${fromY}) to (${toX}, ${toY}): ${error}`);
12154
- throw new Error(`Failed to swipe: ${error}`);
12155
- }
12186
+ const actions = {
12187
+ actions: [
12188
+ {
12189
+ type: 'pointer',
12190
+ id: 'finger1',
12191
+ parameters: {
12192
+ pointerType: 'touch'
12193
+ },
12194
+ actions: [
12195
+ {
12196
+ type: 'pointerMove',
12197
+ duration: 0,
12198
+ x: fromX,
12199
+ y: fromY
12200
+ },
12201
+ {
12202
+ type: 'pointerDown',
12203
+ button: 0
12204
+ },
12205
+ {
12206
+ type: 'pause',
12207
+ duration: 100
12208
+ },
12209
+ {
12210
+ type: 'pointerMove',
12211
+ duration,
12212
+ x: toX,
12213
+ y: toY
12214
+ },
12215
+ {
12216
+ type: 'pointerUp',
12217
+ button: 0
12218
+ }
12219
+ ]
12220
+ }
12221
+ ]
12222
+ };
12223
+ await this.makeRequest('POST', `/session/${this.sessionId}/actions`, actions);
12224
+ debugIOS(`Swiped using W3C Actions from (${fromX}, ${fromY}) to (${toX}, ${toY}) in ${duration}ms`);
12156
12225
  }
12157
12226
  async longPress(x, y, duration = 1000) {
12158
12227
  this.ensureSession();
@@ -12298,8 +12367,7 @@ var __webpack_exports__ = {};
12298
12367
  await this.swipe(from.center[0], from.center[1], to.center[0], to.center[1]);
12299
12368
  }),
12300
12369
  (0, device_namespaceObject.defineActionKeyboardPress)(async (param)=>{
12301
- const key = param.keyName;
12302
- await this.pressKey(key);
12370
+ await this.pressKey(param.keyName);
12303
12371
  }),
12304
12372
  (0, device_namespaceObject.defineAction)({
12305
12373
  name: 'IOSHomeButton',
@@ -12455,23 +12523,23 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12455
12523
  return '';
12456
12524
  }
12457
12525
  async tap(x, y) {
12458
- await this.wdaBackend.tap(x, y);
12526
+ await this.wdaBackend.tap(Math.round(x), Math.round(y));
12459
12527
  }
12460
12528
  async mouseClick(x, y) {
12461
12529
  debugDevice(`mouseClick at coordinates (${x}, ${y})`);
12462
12530
  await this.tap(x, y);
12463
12531
  }
12464
12532
  async doubleTap(x, y) {
12465
- await this.wdaBackend.doubleTap(x, y);
12533
+ await this.wdaBackend.doubleTap(Math.round(x), Math.round(y));
12466
12534
  }
12467
12535
  async tripleTap(x, y) {
12468
- await this.wdaBackend.tripleTap(x, y);
12536
+ await this.wdaBackend.tripleTap(Math.round(x), Math.round(y));
12469
12537
  }
12470
12538
  async longPress(x, y, duration = 1000) {
12471
- await this.wdaBackend.longPress(x, y, duration);
12539
+ await this.wdaBackend.longPress(Math.round(x), Math.round(y), duration);
12472
12540
  }
12473
12541
  async swipe(fromX, fromY, toX, toY, duration = 500) {
12474
- await this.wdaBackend.swipe(fromX, fromY, toX, toY, duration);
12542
+ await this.wdaBackend.swipe(Math.round(fromX), Math.round(fromY), Math.round(toX), Math.round(toY), duration);
12475
12543
  }
12476
12544
  async typeText(text, options) {
12477
12545
  var _this_options;
@@ -12494,49 +12562,49 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12494
12562
  async scrollUp(distance, startPoint) {
12495
12563
  const { width, height } = await this.size();
12496
12564
  const start = startPoint ? {
12497
- x: startPoint.left,
12498
- y: startPoint.top
12565
+ x: Math.round(startPoint.left),
12566
+ y: Math.round(startPoint.top)
12499
12567
  } : {
12500
- x: width / 2,
12501
- y: height / 2
12568
+ x: Math.round(width / 2),
12569
+ y: Math.round(height / 2)
12502
12570
  };
12503
- const scrollDistance = distance || height / 3;
12571
+ const scrollDistance = Math.round(distance || height / 3);
12504
12572
  await this.swipe(start.x, start.y, start.x, start.y + scrollDistance);
12505
12573
  }
12506
12574
  async scrollDown(distance, startPoint) {
12507
12575
  const { width, height } = await this.size();
12508
12576
  const start = startPoint ? {
12509
- x: startPoint.left,
12510
- y: startPoint.top
12577
+ x: Math.round(startPoint.left),
12578
+ y: Math.round(startPoint.top)
12511
12579
  } : {
12512
- x: width / 2,
12513
- y: height / 2
12580
+ x: Math.round(width / 2),
12581
+ y: Math.round(height / 2)
12514
12582
  };
12515
- const scrollDistance = distance || height / 3;
12583
+ const scrollDistance = Math.round(distance || height / 3);
12516
12584
  await this.swipe(start.x, start.y, start.x, start.y - scrollDistance);
12517
12585
  }
12518
12586
  async scrollLeft(distance, startPoint) {
12519
12587
  const { width, height } = await this.size();
12520
12588
  const start = startPoint ? {
12521
- x: startPoint.left,
12522
- y: startPoint.top
12589
+ x: Math.round(startPoint.left),
12590
+ y: Math.round(startPoint.top)
12523
12591
  } : {
12524
- x: width / 2,
12525
- y: height / 2
12592
+ x: Math.round(width / 2),
12593
+ y: Math.round(height / 2)
12526
12594
  };
12527
- const scrollDistance = distance || width / 3;
12595
+ const scrollDistance = Math.round(distance || 0.7 * width);
12528
12596
  await this.swipe(start.x, start.y, start.x + scrollDistance, start.y);
12529
12597
  }
12530
12598
  async scrollRight(distance, startPoint) {
12531
12599
  const { width, height } = await this.size();
12532
12600
  const start = startPoint ? {
12533
- x: startPoint.left,
12534
- y: startPoint.top
12601
+ x: Math.round(startPoint.left),
12602
+ y: Math.round(startPoint.top)
12535
12603
  } : {
12536
- x: width / 2,
12537
- y: height / 2
12604
+ x: Math.round(width / 2),
12605
+ y: Math.round(height / 2)
12538
12606
  };
12539
- const scrollDistance = distance || width / 3;
12607
+ const scrollDistance = Math.round(distance || 0.7 * width);
12540
12608
  await this.swipe(start.x, start.y, start.x - scrollDistance, start.y);
12541
12609
  }
12542
12610
  async scrollUntilTop(startPoint) {
@@ -12577,32 +12645,32 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12577
12645
  const { width, height } = await this.size();
12578
12646
  let start;
12579
12647
  if (startPoint) start = {
12580
- x: startPoint.left,
12581
- y: startPoint.top
12648
+ x: Math.round(startPoint.left),
12649
+ y: Math.round(startPoint.top)
12582
12650
  };
12583
12651
  else switch(direction){
12584
12652
  case 'up':
12585
12653
  start = {
12586
- x: width / 2,
12587
- y: 0.2 * height
12654
+ x: Math.round(width / 2),
12655
+ y: Math.round(0.2 * height)
12588
12656
  };
12589
12657
  break;
12590
12658
  case 'down':
12591
12659
  start = {
12592
- x: width / 2,
12593
- y: 0.8 * height
12660
+ x: Math.round(width / 2),
12661
+ y: Math.round(0.8 * height)
12594
12662
  };
12595
12663
  break;
12596
12664
  case 'left':
12597
12665
  start = {
12598
- x: 0.8 * width,
12599
- y: height / 2
12666
+ x: Math.round(0.8 * width),
12667
+ y: Math.round(height / 2)
12600
12668
  };
12601
12669
  break;
12602
12670
  case 'right':
12603
12671
  start = {
12604
- x: 0.2 * width,
12605
- y: height / 2
12672
+ x: Math.round(0.2 * width),
12673
+ y: Math.round(height / 2)
12606
12674
  };
12607
12675
  break;
12608
12676
  }
@@ -12629,7 +12697,7 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12629
12697
  break;
12630
12698
  }
12631
12699
  lastScreenshot = currentScreenshot;
12632
- const scrollDistance = 'left' === direction || 'right' === direction ? 0.6 * width : 0.6 * height;
12700
+ const scrollDistance = Math.round('left' === direction || 'right' === direction ? 0.6 * width : 0.6 * height);
12633
12701
  debugDevice(`Performing scroll: ${direction}, distance: ${scrollDistance}`);
12634
12702
  switch(direction){
12635
12703
  case 'up':
@@ -12666,9 +12734,9 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12666
12734
  try {
12667
12735
  debugDevice('Triggering app switcher with slow swipe up gesture');
12668
12736
  const { width, height } = await this.size();
12669
- const centerX = width / 2;
12670
- const startY = height - 5;
12671
- const endY = 0.5 * height;
12737
+ const centerX = Math.round(width / 2);
12738
+ const startY = Math.round(height - 5);
12739
+ const endY = Math.round(0.5 * height);
12672
12740
  await this.wdaBackend.swipe(centerX, startY, centerX, endY, 1500);
12673
12741
  await (0, utils_namespaceObject.sleep)(800);
12674
12742
  } catch (error) {
@@ -12686,9 +12754,9 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12686
12754
  return true;
12687
12755
  }
12688
12756
  const windowSize = await this.wdaBackend.getWindowSize();
12689
- const centerX = windowSize.width / 2;
12690
- const startY = 0.33 * windowSize.height;
12691
- const endY = 0.33 * windowSize.height + 10;
12757
+ const centerX = Math.round(windowSize.width / 2);
12758
+ const startY = Math.round(0.33 * windowSize.height);
12759
+ const endY = Math.round(0.33 * windowSize.height + 10);
12692
12760
  await this.swipe(centerX, startY, centerX, endY, 50);
12693
12761
  debugDevice('Dismissed keyboard with swipe down gesture at screen one-third position');
12694
12762
  await (0, utils_namespaceObject.sleep)(300);
@@ -12856,17 +12924,14 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12856
12924
  host: 'localhost',
12857
12925
  port: constants_namespaceObject.DEFAULT_WDA_PORT
12858
12926
  };
12859
- let device;
12860
- let agent;
12861
12927
  let connected = false;
12862
12928
  while(!connected)try {
12863
- device = new device_IOSDevice({
12929
+ const device = new device_IOSDevice({
12864
12930
  wdaHost: wdaConfig.host,
12865
12931
  wdaPort: wdaConfig.port
12866
12932
  });
12867
12933
  console.log(`\u{1F50C} Connecting to WebDriverAgent at ${wdaConfig.host}:${wdaConfig.port}...`);
12868
12934
  await device.connect();
12869
- agent = new IOSAgent(device);
12870
12935
  connected = true;
12871
12936
  const deviceInfo = await device.getConnectedDeviceInfo();
12872
12937
  console.log("\u2705 Connected to WebDriverAgent successfully!");
@@ -12918,7 +12983,15 @@ ScreenSize: ${size.width}x${size.height} (DPR: ${size.scale})
12918
12983
  `);
12919
12984
  else if ('configure' === action) wdaConfig = await configureWebDriverAgent();
12920
12985
  }
12921
- const playgroundServer = new PlaygroundServer(device, agent, staticDir);
12986
+ const agentFactory = async ()=>{
12987
+ const newDevice = new device_IOSDevice({
12988
+ wdaHost: wdaConfig.host,
12989
+ wdaPort: wdaConfig.port
12990
+ });
12991
+ await newDevice.connect();
12992
+ return new IOSAgent(newDevice);
12993
+ };
12994
+ const playgroundServer = new PlaygroundServer(agentFactory, staticDir);
12922
12995
  console.log("\uD83D\uDE80 Starting server...");
12923
12996
  const availablePlaygroundPort = await findAvailablePort(constants_namespaceObject.PLAYGROUND_SERVER_PORT);
12924
12997
  if (availablePlaygroundPort !== constants_namespaceObject.PLAYGROUND_SERVER_PORT) console.log(`\u{26A0}\u{FE0F} Port ${constants_namespaceObject.PLAYGROUND_SERVER_PORT} is busy, using port ${availablePlaygroundPort} instead`);