@midscene/computer 1.9.8 → 1.10.1-beta-20260624112700.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
@@ -424,6 +424,42 @@ function sendKeyViaAppleScript(key, modifiers = []) {
424
424
  script
425
425
  ]);
426
426
  }
427
+ const POWERSHELL_TIMEOUT_MS = 15000;
428
+ const POWERSHELL_MAX_BUFFER = 67108864;
429
+ function escapePowershellSingleQuoted(value) {
430
+ return value.replace(/'/g, "''");
431
+ }
432
+ function runPowershell(script) {
433
+ const encoded = Buffer.from(script, 'utf16le').toString('base64');
434
+ return (0, external_node_child_process_namespaceObject.execFileSync)('powershell.exe', [
435
+ '-NoProfile',
436
+ '-NonInteractive',
437
+ '-ExecutionPolicy',
438
+ 'Bypass',
439
+ '-EncodedCommand',
440
+ encoded
441
+ ], {
442
+ encoding: 'utf8',
443
+ timeout: POWERSHELL_TIMEOUT_MS,
444
+ maxBuffer: POWERSHELL_MAX_BUFFER,
445
+ windowsHide: true
446
+ });
447
+ }
448
+ function listWindowsDisplays() {
449
+ const script = `
450
+ Add-Type -AssemblyName System.Windows.Forms
451
+ $s = [System.Windows.Forms.Screen]::AllScreens | ForEach-Object {
452
+ [PSCustomObject]@{ id = $_.DeviceName; name = $_.DeviceName; primary = $_.Primary }
453
+ }
454
+ ConvertTo-Json @($s) -Compress
455
+ `.trim();
456
+ const parsed = JSON.parse(runPowershell(script).trim());
457
+ return parsed.map((d)=>({
458
+ id: String(d.id),
459
+ name: d.name || String(d.id),
460
+ primary: d.primary || false
461
+ }));
462
+ }
427
463
  let device_libnut = null;
428
464
  let libnutLoadError = null;
429
465
  async function getLibnut() {
@@ -690,6 +726,7 @@ class ComputerDevice {
690
726
  }
691
727
  static async listDisplays() {
692
728
  try {
729
+ if ('win32' === process.platform) return listWindowsDisplays();
693
730
  const displays = await external_screenshot_desktop_default().listDisplays();
694
731
  return displays.map((d)=>({
695
732
  id: String(d.id),
@@ -747,7 +784,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
747
784
  }
748
785
  async healthCheck() {
749
786
  console.log('[HealthCheck] Starting health check...');
750
- console.log("[HealthCheck] @midscene/computer v1.9.8");
787
+ console.log("[HealthCheck] @midscene/computer v1.10.1-beta-20260624112700.0");
751
788
  console.log('[HealthCheck] Taking screenshot...');
752
789
  const screenshotTimeout = 15000;
753
790
  let timeoutId;
@@ -816,6 +853,7 @@ Available Displays: ${displays.length > 0 ? displays.map((d)=>d.name).join(', ')
816
853
  debugDevice('Taking screenshot', {
817
854
  displayId: this.displayId
818
855
  });
856
+ if ('win32' === process.platform) return this.screenshotViaPowershell();
819
857
  const options = {
820
858
  format: 'png'
821
859
  };
@@ -849,6 +887,40 @@ Please follow these steps:
849
887
  Original error: ${lastRawMessage}`);
850
888
  throw new Error(`Failed to take screenshot: ${lastRawMessage}`);
851
889
  }
890
+ screenshotViaPowershell() {
891
+ const deviceName = this.displayId ? String(this.displayId) : '';
892
+ const target = deviceName ? `[System.Windows.Forms.Screen]::AllScreens | Where-Object { $_.DeviceName -eq '${escapePowershellSingleQuoted(deviceName)}' } | Select-Object -First 1` : '$null';
893
+ const script = `
894
+ $ErrorActionPreference = 'Stop'
895
+ Add-Type -AssemblyName System.Windows.Forms, System.Drawing
896
+ Add-Type @"
897
+ using System;
898
+ using System.Runtime.InteropServices;
899
+ public class NutDpi { [DllImport("user32.dll")] public static extern bool SetProcessDPIAware(); }
900
+ "@
901
+ [NutDpi]::SetProcessDPIAware() | Out-Null
902
+ $screen = ${target}
903
+ if (-not $screen) { $screen = [System.Windows.Forms.Screen]::PrimaryScreen }
904
+ $b = $screen.Bounds
905
+ $bmp = New-Object System.Drawing.Bitmap($b.Width, $b.Height)
906
+ $g = [System.Drawing.Graphics]::FromImage($bmp)
907
+ $g.CopyFromScreen($b.X, $b.Y, 0, 0, $bmp.Size)
908
+ $ms = New-Object System.IO.MemoryStream
909
+ $bmp.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
910
+ [Console]::Out.Write([Convert]::ToBase64String($ms.ToArray()))
911
+ $g.Dispose(); $bmp.Dispose(); $ms.Dispose()
912
+ `.trim();
913
+ let stdout;
914
+ try {
915
+ stdout = runPowershell(script);
916
+ } catch (error) {
917
+ const message = error instanceof Error ? error.message : String(error);
918
+ throw new Error(`Failed to take screenshot on Windows: ${message}`);
919
+ }
920
+ const body = stdout.trim();
921
+ if (!body) throw new Error('Failed to take screenshot on Windows: PowerShell returned no image data');
922
+ return (0, img_namespaceObject.createImgBase64ByFormat)('png', body);
923
+ }
852
924
  async size() {
853
925
  if (this.displayGeometry) return {
854
926
  width: Math.round(this.displayGeometry.bounds.width),
@@ -1972,9 +2044,9 @@ async function agentForRDPComputer(opts) {
1972
2044
  return new ComputerAgent(device, opts);
1973
2045
  }
1974
2046
  const core_namespaceObject = require("@midscene/core");
1975
- const agent_behavior_init_args_namespaceObject = require("@midscene/shared/mcp/agent-behavior-init-args");
1976
- const base_tools_namespaceObject = require("@midscene/shared/mcp/base-tools");
1977
- function mcp_tools_define_property(obj, key, value) {
2047
+ const agent_behavior_init_args_namespaceObject = require("@midscene/shared/agent-tools/agent-behavior-init-args");
2048
+ const base_tools_namespaceObject = require("@midscene/shared/agent-tools/base-tools");
2049
+ function agent_tools_define_property(obj, key, value) {
1978
2050
  if (key in obj) Object.defineProperty(obj, key, {
1979
2051
  value: value,
1980
2052
  enumerable: true,
@@ -1984,7 +2056,7 @@ function mcp_tools_define_property(obj, key, value) {
1984
2056
  else obj[key] = value;
1985
2057
  return obj;
1986
2058
  }
1987
- const mcp_tools_debug = (0, logger_namespaceObject.getDebug)('mcp:computer-tools');
2059
+ const agent_tools_debug = (0, logger_namespaceObject.getDebug)('agent-tools:computer');
1988
2060
  const RDP_SECURITY_PROTOCOLS = [
1989
2061
  'auto',
1990
2062
  'tls',
@@ -2052,14 +2124,14 @@ class ComputerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools
2052
2124
  try {
2053
2125
  await this.agent.destroy?.();
2054
2126
  } catch (error) {
2055
- mcp_tools_debug('Failed to destroy agent during cleanup:', error);
2127
+ agent_tools_debug('Failed to destroy agent during cleanup:', error);
2056
2128
  }
2057
2129
  this.agent = void 0;
2058
2130
  }
2059
2131
  if (this.agent) return this.agent;
2060
2132
  const reportOptions = this.readCliReportAgentOptions();
2061
2133
  if (opts?.mode === 'rdp') {
2062
- mcp_tools_debug('Creating RDP Computer agent for host:', opts.host);
2134
+ agent_tools_debug('Creating RDP Computer agent for host:', opts.host);
2063
2135
  const { mode: _mode, ...rdpFields } = opts;
2064
2136
  const agent = await agentForRDPComputer({
2065
2137
  ...rdpFields,
@@ -2071,7 +2143,7 @@ class ComputerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools
2071
2143
  }
2072
2144
  const displayId = opts?.mode === 'local' ? opts.displayId : void 0;
2073
2145
  const headless = opts?.mode === 'local' ? opts.headless : void 0;
2074
- mcp_tools_debug('Creating Computer agent with displayId:', displayId || 'primary');
2146
+ agent_tools_debug('Creating Computer agent with displayId:', displayId || 'primary');
2075
2147
  const agentOpts = {
2076
2148
  ...displayId ? {
2077
2149
  displayId
@@ -2102,7 +2174,7 @@ class ComputerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools
2102
2174
  try {
2103
2175
  await this.agent.destroy?.();
2104
2176
  } catch (error) {
2105
- mcp_tools_debug('Failed to destroy agent during connect:', error);
2177
+ agent_tools_debug('Failed to destroy agent during connect:', error);
2106
2178
  }
2107
2179
  this.agent = void 0;
2108
2180
  this.lastInitArgsSignature = void 0;
@@ -2145,7 +2217,7 @@ class ComputerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools
2145
2217
  ];
2146
2218
  }
2147
2219
  constructor(...args){
2148
- super(...args), mcp_tools_define_property(this, "lastInitArgsSignature", void 0), mcp_tools_define_property(this, "initArgSpec", {
2220
+ super(...args), agent_tools_define_property(this, "lastInitArgsSignature", void 0), agent_tools_define_property(this, "initArgSpec", {
2149
2221
  namespace: 'computer',
2150
2222
  shape: computerInitArgShape,
2151
2223
  cli: {
@@ -2157,7 +2229,7 @@ class ComputerMidsceneTools extends base_tools_namespaceObject.BaseMidsceneTools
2157
2229
  }
2158
2230
  const env_namespaceObject = require("@midscene/shared/env");
2159
2231
  function version() {
2160
- const currentVersion = "1.9.8";
2232
+ const currentVersion = "1.10.1-beta-20260624112700.0";
2161
2233
  console.log(`@midscene/computer v${currentVersion}`);
2162
2234
  return currentVersion;
2163
2235
  }
@@ -1,17 +1,17 @@
1
1
  import { AbstractInterface } from '@midscene/core/device';
2
2
  import { Agent } from '@midscene/core/agent';
3
- import { AgentBehaviorInitArgs } from '@midscene/shared/mcp/agent-behavior-init-args';
3
+ import { AgentBehaviorInitArgs } from '@midscene/shared/agent-tools/agent-behavior-init-args';
4
4
  import { AgentOpt } from '@midscene/core/agent';
5
- import { BaseMidsceneTools } from '@midscene/shared/mcp/base-tools';
5
+ import { BaseMidsceneTools } from '@midscene/shared/agent-tools/base-tools';
6
6
  import { ChildProcessWithoutNullStreams } from 'node:child_process';
7
7
  import { ComputerInputPrimitives } from '@midscene/core/device';
8
8
  import type { DeviceAction } from '@midscene/core';
9
- import { InitArgSpec } from '@midscene/shared/mcp/base-tools';
9
+ import { InitArgSpec } from '@midscene/shared/agent-tools/base-tools';
10
10
  import type { InterfaceType } from '@midscene/core';
11
11
  import { overrideAIConfig } from '@midscene/shared/env';
12
12
  import type { Size } from '@midscene/core';
13
13
  import { SpawnOptionsWithoutStdio } from 'node:child_process';
14
- import type { ToolDefinition } from '@midscene/shared/mcp/types';
14
+ import type { ToolDefinition } from '@midscene/shared/agent-tools/types';
15
15
 
16
16
  declare interface AccessibilityCheckResult {
17
17
  hasPermission: boolean;
@@ -101,6 +101,20 @@ export declare class ComputerDevice implements AbstractInterface {
101
101
  */
102
102
  private isRunningAsAdmin;
103
103
  screenshotBase64(): Promise<string>;
104
+ /**
105
+ * Windows screenshot path that bypasses screenshot-desktop's polyglot .bat
106
+ * (see screenshotBase64 for the rationale). Captures via PowerShell +
107
+ * System.Drawing, which honors `displayId` by matching the monitor's
108
+ * DeviceName and captures in virtual-desktop coordinates, so secondary
109
+ * displays — including those at negative offsets — are supported.
110
+ *
111
+ * Note: the script makes the process system-DPI-aware (SetProcessDPIAware)
112
+ * so captures return physical pixels. On mixed-DPI multi-monitor setups a
113
+ * non-primary monitor may still be off by its per-monitor scale factor;
114
+ * system DPI awareness covers the common single-scale and uniform-scale
115
+ * cases that #2150 reports.
116
+ */
117
+ private screenshotViaPowershell;
104
118
  size(): Promise<Size>;
105
119
  private toGlobalPoint;
106
120
  /**
@@ -153,7 +167,7 @@ export declare interface ComputerDeviceOpt {
153
167
  /**
154
168
  * Discriminated union describing the two ways `computer_*` tools can spawn an
155
169
  * agent. `mode` is filled in by `initArgSpec.adapt` based on whether `host` is
156
- * set, so callers (CLI/MCP/YAML) never have to provide it explicitly.
170
+ * set, so callers (CLI/YAML) never have to provide it explicitly.
157
171
  */
158
172
  declare type ComputerInitArgs = ComputerLocalInitArgs | ComputerRDPInitArgs;
159
173
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@midscene/computer",
3
- "version": "1.9.8",
3
+ "version": "1.10.1-beta-20260624112700.0",
4
4
  "description": "Midscene.js Computer Desktop Automation",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -27,19 +27,14 @@
27
27
  "import": "./dist/es/index.mjs",
28
28
  "require": "./dist/lib/index.js"
29
29
  },
30
- "./mcp-server": {
31
- "types": "./dist/types/mcp-server.d.ts",
32
- "import": "./dist/es/mcp-server.mjs",
33
- "require": "./dist/lib/mcp-server.js"
34
- },
35
30
  "./package.json": "./package.json"
36
31
  },
37
32
  "dependencies": {
38
33
  "@computer-use/libnut": "^4.2.0",
39
34
  "clipboardy": "^4.0.0",
40
35
  "screenshot-desktop": "^1.15.3",
41
- "@midscene/core": "1.9.8",
42
- "@midscene/shared": "1.9.8"
36
+ "@midscene/shared": "1.10.1-beta-20260624112700.0",
37
+ "@midscene/core": "1.10.1-beta-20260624112700.0"
43
38
  },
44
39
  "optionalDependencies": {
45
40
  "node-mac-permissions": "2.5.0"