@midscene/computer 1.13.4-beta-20260928083351.0 → 1.14.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/cli.mjs CHANGED
@@ -86,24 +86,6 @@ function sendKeyViaAppleScript(key, modifiers = []) {
86
86
  script
87
87
  ]);
88
88
  }
89
- const desktopPointerPolicy = {
90
- uiSettleMs: 100,
91
- moveSettleMs: 50,
92
- defaultTapHoldMs: 100,
93
- tapMoveSteps: 8,
94
- tapMoveStepDelayMs: 8,
95
- hoverMoveSteps: 10,
96
- hoverMoveStepDelayMs: 10
97
- };
98
- const desktopKeyboardPolicy = {
99
- focusBeforeTypeMs: 300,
100
- focusBeforeClearMs: 300,
101
- focusBeforeShortcutMs: 50,
102
- afterClearMs: 150
103
- };
104
- function resolveTapHoldDuration(duration) {
105
- return Math.max(0, Math.round(duration ?? desktopPointerPolicy.defaultTapHoldMs));
106
- }
107
89
  function _define_property(obj, key, value) {
108
90
  if (key in obj) Object.defineProperty(obj, key, {
109
91
  value: value,
@@ -793,9 +775,18 @@ async function captureScreenshot(options) {
793
775
  });
794
776
  }
795
777
  }
778
+ const SMOOTH_MOVE_STEPS_TAP = 8;
779
+ const SMOOTH_MOVE_STEPS_MOUSE_MOVE = 10;
796
780
  const SMOOTH_MOVE_STEPS_DRAG = 20;
781
+ const SMOOTH_MOVE_DELAY_TAP = 8;
782
+ const SMOOTH_MOVE_DELAY_MOUSE_MOVE = 10;
797
783
  const SMOOTH_MOVE_DELAY_DRAG = 10;
784
+ const MOUSE_MOVE_EFFECT_WAIT = 300;
785
+ const CLICK_SETTLE_DELAY = 50;
786
+ const CLICK_HOLD_DURATION = 100;
798
787
  const CLICK_FOCUS_SETTLE_DELAY = 120;
788
+ const INPUT_FOCUS_DELAY = 300;
789
+ const INPUT_CLEAR_DELAY = 150;
799
790
  const SCROLL_STEP_DELAY = 100;
800
791
  const SCROLL_COMPLETE_DELAY = 500;
801
792
  const EDGE_SCROLL_TOTAL_PX = 50000;
@@ -1116,7 +1107,7 @@ function normalizePrimaryKey(key) {
1116
1107
  return KEY_NAME_MAP[lowerKey] || lowerKey;
1117
1108
  }
1118
1109
  class ComputerDevice {
1119
- async moveGlobalPointer(point, context, options) {
1110
+ async moveGlobalPointer(point, context, smooth) {
1120
1111
  if (this.destroyed) throw new Error('ComputerDevice has been destroyed');
1121
1112
  const target = {
1122
1113
  x: Math.round(point.x),
@@ -1124,21 +1115,21 @@ class ComputerDevice {
1124
1115
  };
1125
1116
  if ('win32' === process.platform) {
1126
1117
  const actual = this.windowsPointerDriver.moveTo(target, {
1127
- smoothSteps: options?.smoothSteps,
1128
- smoothDelayMs: options?.smoothDelay
1118
+ smoothSteps: smooth?.smoothSteps,
1119
+ smoothDelayMs: smooth?.smoothDelay
1129
1120
  });
1130
1121
  const drift = windowsPointerDrift(target, actual);
1131
1122
  if (!windowsPointerIsWithinTolerance(drift)) throw new Error(`${context}: expected (${target.x}, ${target.y}), got (${actual.x}, ${actual.y}), drift=(${drift.x}, ${drift.y})`);
1132
- await this.inputDriver.delay(options?.settleDelayMs ?? desktopPointerPolicy.moveSettleMs);
1123
+ await this.inputDriver.delay(CLICK_SETTLE_DELAY);
1133
1124
  return actual;
1134
1125
  }
1135
- if (options?.smoothSteps !== void 0 && void 0 !== options.smoothDelay) await this.inputDriver.smoothMoveMouse(target.x, target.y, options.smoothSteps, options.smoothDelay);
1126
+ if (smooth) await this.inputDriver.smoothMoveMouse(target.x, target.y, smooth.smoothSteps, smooth.smoothDelay);
1136
1127
  else this.inputDriver.moveMouse(target.x, target.y);
1137
- await this.inputDriver.delay(options?.settleDelayMs ?? desktopPointerPolicy.moveSettleMs);
1128
+ await this.inputDriver.delay(CLICK_SETTLE_DELAY);
1138
1129
  return this.inputDriver.getMousePos();
1139
1130
  }
1140
- moveDisplayPointer(point, context, options) {
1141
- return this.moveGlobalPointer(this.toGlobalPoint(point), context, options);
1131
+ moveDisplayPointer(point, context, smooth) {
1132
+ return this.moveGlobalPointer(this.toGlobalPoint(point), context, smooth);
1142
1133
  }
1143
1134
  async performPointerDrag(from, to, duration) {
1144
1135
  const screenSize = await this.size();
@@ -1164,9 +1155,7 @@ class ComputerDevice {
1164
1155
  await this.moveDisplayPointer({
1165
1156
  x,
1166
1157
  y
1167
- }, 'Mouse did not reach the keyboard focus target', {
1168
- settleDelayMs: desktopPointerPolicy.uiSettleMs
1169
- });
1158
+ }, 'Mouse did not reach the keyboard focus target');
1170
1159
  this.inputDriver.mouseClick('left');
1171
1160
  }
1172
1161
  await this.inputDriver.delay(delayMs);
@@ -1248,7 +1237,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
1248
1237
  }
1249
1238
  async healthCheck(displays) {
1250
1239
  console.log('[HealthCheck] Starting health check...');
1251
- console.log("[HealthCheck] @midscene/computer v1.13.4-beta-20260928083351.0");
1240
+ console.log("[HealthCheck] @midscene/computer v1.14.0");
1252
1241
  console.log('[HealthCheck] Taking screenshot...');
1253
1242
  const screenshotTimeout = 15000;
1254
1243
  let timeoutId;
@@ -1286,7 +1275,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
1286
1275
  console.log(`[HealthCheck] Moving mouse to (${targetX}, ${targetY})...`);
1287
1276
  try {
1288
1277
  this.inputDriver.moveMouse(targetX, targetY);
1289
- await sleep(desktopPointerPolicy.moveSettleMs);
1278
+ await sleep(CLICK_SETTLE_DELAY);
1290
1279
  this.inputDriver.assertMousePosition(targetX, targetY, 'Mouse health check failed');
1291
1280
  } finally{
1292
1281
  this.inputDriver.moveMouse(startPos.x, startPos.y);
@@ -1521,9 +1510,8 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
1521
1510
  const screenSize = await this.size();
1522
1511
  if ('win32' === process.platform && this.inputDriver.focusActiveWindow()) await this.inputDriver.delay(CLICK_FOCUS_SETTLE_DELAY);
1523
1512
  const point = this.resolveUntargetedScrollPoint(screenSize);
1524
- await this.moveGlobalPointer(point, 'Mouse did not reach the scroll viewport', {
1525
- settleDelayMs: desktopPointerPolicy.uiSettleMs
1526
- });
1513
+ await this.moveGlobalPointer(point, 'Mouse did not reach the scroll viewport');
1514
+ await this.inputDriver.delay(MOUSE_MOVE_EFFECT_WAIT);
1527
1515
  return screenSize;
1528
1516
  }
1529
1517
  async performScroll(param) {
@@ -1664,7 +1652,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
1664
1652
  });
1665
1653
  const targetX = Math.round(target.x);
1666
1654
  const targetY = Math.round(target.y);
1667
- const holdDuration = resolveTapHoldDuration(opts?.duration);
1655
+ const holdDuration = Math.max(0, Math.round(opts?.duration ?? CLICK_HOLD_DURATION));
1668
1656
  debugComputerInput('tap start %o', {
1669
1657
  local: {
1670
1658
  x,
@@ -1683,9 +1671,8 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
1683
1671
  x: targetX,
1684
1672
  y: targetY
1685
1673
  }, 'Mouse did not reach the tap target', {
1686
- smoothSteps: desktopPointerPolicy.tapMoveSteps,
1687
- smoothDelay: desktopPointerPolicy.tapMoveStepDelayMs,
1688
- settleDelayMs: desktopPointerPolicy.uiSettleMs
1674
+ smoothSteps: SMOOTH_MOVE_STEPS_TAP,
1675
+ smoothDelay: SMOOTH_MOVE_DELAY_TAP
1689
1676
  });
1690
1677
  await pressMouseAtGlobalPoint(this.inputDriver, targetX, targetY, current, holdDuration, 'primary');
1691
1678
  if (frontmostBefore && 'darwin' === process.platform) {
@@ -1701,9 +1688,7 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
1701
1688
  const followUpCurrent = await this.moveGlobalPointer({
1702
1689
  x: targetX,
1703
1690
  y: targetY
1704
- }, 'Mouse did not reach the focus follow-up target', {
1705
- settleDelayMs: desktopPointerPolicy.uiSettleMs
1706
- });
1691
+ }, 'Mouse did not reach the focus follow-up target');
1707
1692
  await pressMouseAtGlobalPoint(this.inputDriver, targetX, targetY, followUpCurrent, holdDuration, 'focus-follow-up');
1708
1693
  }
1709
1694
  }
@@ -1712,18 +1697,14 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
1712
1697
  await this.moveDisplayPointer({
1713
1698
  x,
1714
1699
  y
1715
- }, 'Mouse did not reach the double-click target', {
1716
- settleDelayMs: desktopPointerPolicy.uiSettleMs
1717
- });
1700
+ }, 'Mouse did not reach the double-click target');
1718
1701
  this.inputDriver.mouseClick('left', true);
1719
1702
  },
1720
1703
  rightClick: async ({ x, y })=>{
1721
1704
  await this.moveDisplayPointer({
1722
1705
  x,
1723
1706
  y
1724
- }, 'Mouse did not reach the right-click target', {
1725
- settleDelayMs: desktopPointerPolicy.uiSettleMs
1726
- });
1707
+ }, 'Mouse did not reach the right-click target');
1727
1708
  this.inputDriver.mouseClick('right');
1728
1709
  },
1729
1710
  hover: async ({ x, y })=>{
@@ -1731,10 +1712,10 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
1731
1712
  x,
1732
1713
  y
1733
1714
  }, 'Mouse did not reach the hover target', {
1734
- smoothSteps: desktopPointerPolicy.hoverMoveSteps,
1735
- smoothDelay: desktopPointerPolicy.hoverMoveStepDelayMs,
1736
- settleDelayMs: desktopPointerPolicy.uiSettleMs
1715
+ smoothSteps: SMOOTH_MOVE_STEPS_MOUSE_MOVE,
1716
+ smoothDelay: SMOOTH_MOVE_DELAY_MOUSE_MOVE
1737
1717
  });
1718
+ await this.inputDriver.delay(MOUSE_MOVE_EFFECT_WAIT);
1738
1719
  },
1739
1720
  dragAndDrop: async (from, to)=>{
1740
1721
  await this.performPointerDrag(from, to);
@@ -1749,25 +1730,23 @@ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
1749
1730
  const resolvedInputOptions = resolveTextInputOptions(opts, this.options);
1750
1731
  const element = opts?.target;
1751
1732
  if (element) {
1752
- await this.focusKeyboardTarget(element, desktopKeyboardPolicy.focusBeforeTypeMs);
1753
- if (opts?.focusOnly) return;
1733
+ await this.focusKeyboardTarget(element, INPUT_FOCUS_DELAY);
1754
1734
  if (opts?.replace !== false) {
1755
1735
  await this.selectAllAndDelete();
1756
- await this.inputDriver.delay(desktopKeyboardPolicy.afterClearMs);
1736
+ await this.inputDriver.delay(INPUT_CLEAR_DELAY);
1757
1737
  }
1758
1738
  }
1759
- if (opts?.focusOnly || !value) return;
1760
1739
  await this.smartTypeString(value, resolvedInputOptions);
1761
1740
  },
1762
1741
  keyboardPress: async (keyName, opts)=>{
1763
1742
  const target = opts?.target;
1764
- if (target) await this.focusKeyboardTarget(target, desktopKeyboardPolicy.focusBeforeShortcutMs);
1743
+ if (target) await this.focusKeyboardTarget(target, 50);
1765
1744
  await this.pressKeyboardShortcut(keyName);
1766
1745
  },
1767
1746
  clearInput: async (target)=>{
1768
- if (target) await this.focusKeyboardTarget(target, desktopKeyboardPolicy.focusBeforeClearMs);
1747
+ if (target) await this.focusKeyboardTarget(target, 100);
1769
1748
  await this.selectAllAndDelete();
1770
- await this.inputDriver.delay(desktopKeyboardPolicy.afterClearMs);
1749
+ await this.inputDriver.delay(50);
1771
1750
  }
1772
1751
  },
1773
1752
  scroll: {
@@ -2180,9 +2159,17 @@ function rdp_device_define_property(obj, key, value) {
2180
2159
  return obj;
2181
2160
  }
2182
2161
  const device_debug = getDebug('rdp:device');
2162
+ const device_SMOOTH_MOVE_STEPS_TAP = 8;
2163
+ const device_SMOOTH_MOVE_STEPS_MOUSE_MOVE = 10;
2183
2164
  const device_SMOOTH_MOVE_STEPS_DRAG = 12;
2165
+ const device_SMOOTH_MOVE_DELAY_TAP = 8;
2166
+ const device_SMOOTH_MOVE_DELAY_MOUSE_MOVE = 10;
2184
2167
  const device_SMOOTH_MOVE_DELAY_DRAG = 10;
2168
+ const device_MOUSE_MOVE_EFFECT_WAIT = 300;
2169
+ const device_CLICK_HOLD_DURATION = 50;
2185
2170
  const DRAG_HOLD_DURATION = 100;
2171
+ const device_INPUT_FOCUS_DELAY = 300;
2172
+ const device_INPUT_CLEAR_DELAY = 150;
2186
2173
  const device_SCROLL_STEP_DELAY = 100;
2187
2174
  const device_SCROLL_COMPLETE_DELAY = 500;
2188
2175
  const DEFAULT_SCROLL_DISTANCE = 480;
@@ -2268,6 +2255,12 @@ class RDPDevice {
2268
2255
  throwIfDestroyed() {
2269
2256
  if (this.destroyed) throw new Error('RDPDevice has been destroyed');
2270
2257
  }
2258
+ async moveToElement(element, options) {
2259
+ this.assertConnected();
2260
+ const targetX = Math.round(element.center[0]);
2261
+ const targetY = Math.round(element.center[1]);
2262
+ await this.movePointer(targetX, targetY, options);
2263
+ }
2271
2264
  async clearInput() {
2272
2265
  if (this.backend.clearInput) return void await this.backend.clearInput();
2273
2266
  await this.backend.keyPress('Control+A');
@@ -2321,8 +2314,8 @@ class RDPDevice {
2321
2314
  const boundedFrom = clampPointerPointToSize(from, screenSize);
2322
2315
  const boundedTo = clampPointerPointToSize(to, screenSize);
2323
2316
  await this.movePointer(Math.round(boundedFrom.x), Math.round(boundedFrom.y), {
2324
- steps: desktopPointerPolicy.tapMoveSteps,
2325
- stepDelayMs: desktopPointerPolicy.tapMoveStepDelayMs
2317
+ steps: device_SMOOTH_MOVE_STEPS_TAP,
2318
+ stepDelayMs: device_SMOOTH_MOVE_DELAY_TAP
2326
2319
  });
2327
2320
  await this.backend.mouseButton('left', 'down');
2328
2321
  try {
@@ -2358,40 +2351,34 @@ class RDPDevice {
2358
2351
  rdp_device_define_property(this, "uri", void 0);
2359
2352
  rdp_device_define_property(this, "inputPrimitives", {
2360
2353
  pointer: {
2361
- tap: async ({ x, y }, opts)=>{
2354
+ tap: async ({ x, y })=>{
2362
2355
  await this.movePointer(Math.round(x), Math.round(y), {
2363
- steps: desktopPointerPolicy.tapMoveSteps,
2364
- stepDelayMs: desktopPointerPolicy.tapMoveStepDelayMs,
2365
- settleDelayMs: desktopPointerPolicy.uiSettleMs
2356
+ steps: device_SMOOTH_MOVE_STEPS_TAP,
2357
+ stepDelayMs: device_SMOOTH_MOVE_DELAY_TAP
2366
2358
  });
2367
2359
  await this.backend.mouseButton('left', 'down');
2368
- try {
2369
- await sleep(resolveTapHoldDuration(opts?.duration));
2370
- } finally{
2371
- await this.backend.mouseButton('left', 'up');
2372
- }
2360
+ await sleep(device_CLICK_HOLD_DURATION);
2361
+ await this.backend.mouseButton('left', 'up');
2373
2362
  },
2374
2363
  doubleClick: async ({ x, y })=>{
2375
2364
  await this.movePointer(Math.round(x), Math.round(y), {
2376
- steps: desktopPointerPolicy.tapMoveSteps,
2377
- stepDelayMs: desktopPointerPolicy.tapMoveStepDelayMs,
2378
- settleDelayMs: desktopPointerPolicy.uiSettleMs
2365
+ steps: device_SMOOTH_MOVE_STEPS_TAP,
2366
+ stepDelayMs: device_SMOOTH_MOVE_DELAY_TAP
2379
2367
  });
2380
2368
  await this.backend.mouseButton('left', 'doubleClick');
2381
2369
  },
2382
2370
  rightClick: async ({ x, y })=>{
2383
2371
  await this.movePointer(Math.round(x), Math.round(y), {
2384
- steps: desktopPointerPolicy.tapMoveSteps,
2385
- stepDelayMs: desktopPointerPolicy.tapMoveStepDelayMs,
2386
- settleDelayMs: desktopPointerPolicy.uiSettleMs
2372
+ steps: device_SMOOTH_MOVE_STEPS_TAP,
2373
+ stepDelayMs: device_SMOOTH_MOVE_DELAY_TAP
2387
2374
  });
2388
2375
  await this.backend.mouseButton('right', 'click');
2389
2376
  },
2390
2377
  hover: async ({ x, y })=>{
2391
2378
  await this.movePointer(Math.round(x), Math.round(y), {
2392
- steps: desktopPointerPolicy.hoverMoveSteps,
2393
- stepDelayMs: desktopPointerPolicy.hoverMoveStepDelayMs,
2394
- settleDelayMs: desktopPointerPolicy.uiSettleMs
2379
+ steps: device_SMOOTH_MOVE_STEPS_MOUSE_MOVE,
2380
+ stepDelayMs: device_SMOOTH_MOVE_DELAY_MOUSE_MOVE,
2381
+ settleDelayMs: device_MOUSE_MOVE_EFFECT_WAIT
2395
2382
  });
2396
2383
  },
2397
2384
  dragAndDrop: async (from, to)=>{
@@ -2412,12 +2399,11 @@ class RDPDevice {
2412
2399
  x: target.center[0],
2413
2400
  y: target.center[1]
2414
2401
  });
2415
- await sleep(desktopKeyboardPolicy.focusBeforeTypeMs);
2416
- if (opts?.focusOnly) return;
2417
- if (opts?.replace !== false) {
2418
- await this.clearInput();
2419
- await sleep(desktopKeyboardPolicy.afterClearMs);
2420
- }
2402
+ await sleep(device_INPUT_FOCUS_DELAY);
2403
+ }
2404
+ if (opts?.replace !== false) {
2405
+ await this.clearInput();
2406
+ await sleep(device_INPUT_CLEAR_DELAY);
2421
2407
  }
2422
2408
  if (opts?.focusOnly || !value) return;
2423
2409
  await this.typeText(value, resolvedInputOptions);
@@ -2430,21 +2416,18 @@ class RDPDevice {
2430
2416
  x: element.center[0],
2431
2417
  y: element.center[1]
2432
2418
  });
2433
- await sleep(desktopKeyboardPolicy.focusBeforeClearMs);
2419
+ await sleep(device_INPUT_FOCUS_DELAY);
2434
2420
  }
2435
2421
  await this.clearInput();
2436
- await sleep(desktopKeyboardPolicy.afterClearMs);
2422
+ await sleep(device_INPUT_CLEAR_DELAY);
2437
2423
  },
2438
2424
  keyboardPress: async (keyName, opts)=>{
2439
2425
  this.assertConnected();
2440
2426
  const target = opts?.target;
2441
- if (target) {
2442
- await this.inputPrimitives.pointer.tap({
2443
- x: target.center[0],
2444
- y: target.center[1]
2445
- });
2446
- await sleep(desktopKeyboardPolicy.focusBeforeShortcutMs);
2447
- }
2427
+ if (target) await this.inputPrimitives.pointer.tap({
2428
+ x: target.center[0],
2429
+ y: target.center[1]
2430
+ });
2448
2431
  await this.backend.keyPress(keyName);
2449
2432
  }
2450
2433
  },
@@ -2452,27 +2435,17 @@ class RDPDevice {
2452
2435
  scroll: async (param)=>{
2453
2436
  this.assertConnected();
2454
2437
  const target = param.locate;
2455
- let scrollPoint;
2456
- if (target) scrollPoint = target.center;
2457
- else {
2458
- const size = await this.size();
2459
- scrollPoint = [
2460
- Math.round(size.width / 2),
2461
- Math.round(size.height / 2)
2462
- ];
2463
- }
2464
- await this.movePointer(Math.round(scrollPoint[0]), Math.round(scrollPoint[1]), {
2465
- steps: desktopPointerPolicy.hoverMoveSteps,
2466
- stepDelayMs: desktopPointerPolicy.hoverMoveStepDelayMs,
2467
- settleDelayMs: target ? desktopPointerPolicy.moveSettleMs : desktopPointerPolicy.uiSettleMs
2438
+ if (target) await this.moveToElement(target, {
2439
+ steps: device_SMOOTH_MOVE_STEPS_MOUSE_MOVE,
2440
+ stepDelayMs: device_SMOOTH_MOVE_DELAY_MOUSE_MOVE
2468
2441
  });
2469
2442
  if (param.scrollType && 'singleAction' !== param.scrollType) {
2470
2443
  const direction = this.edgeScrollDirection(param.scrollType);
2471
- for(let i = 0; i < device_EDGE_SCROLL_STEPS; i++)await this.performWheel(direction, DEFAULT_SCROLL_DISTANCE, scrollPoint[0], scrollPoint[1]);
2444
+ for(let i = 0; i < device_EDGE_SCROLL_STEPS; i++)await this.performWheel(direction, DEFAULT_SCROLL_DISTANCE, target?.center[0], target?.center[1]);
2472
2445
  await sleep(device_SCROLL_COMPLETE_DELAY);
2473
2446
  return;
2474
2447
  }
2475
- await this.performWheel(param.direction || 'down', param.distance || this.defaultScrollDistance(param.direction || 'down'), scrollPoint[0], scrollPoint[1]);
2448
+ await this.performWheel(param.direction || 'down', param.distance || this.defaultScrollDistance(param.direction || 'down'), target?.center[0], target?.center[1]);
2476
2449
  await sleep(device_SCROLL_COMPLETE_DELAY);
2477
2450
  }
2478
2451
  }
@@ -2753,7 +2726,7 @@ const tools = new ComputerMidsceneTools({
2753
2726
  });
2754
2727
  runToolsCLI(tools, 'midscene-computer', {
2755
2728
  stripPrefix: 'computer_',
2756
- version: "1.13.4-beta-20260928083351.0",
2729
+ version: "1.14.0",
2757
2730
  extraCommands: createReportCliCommands()
2758
2731
  }).catch((e)=>{
2759
2732
  process.exit(reportCLIError(e));