automify 0.1.8 → 0.1.9

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/README.md CHANGED
@@ -14,14 +14,14 @@ Computer use surfaces:
14
14
  | -------------- | --------------------------- | ----------------------------------------------------------- |
15
15
  | Browser | `automify.browser()` | Playwright browser with screenshots and actions |
16
16
  | Desktop | `automify.localComputer()` | Native desktop on the current macOS, Windows, or Linux host |
17
- | Docker desktop | `automify.dockerComputer()` | Linux desktop inside a Docker container |
17
+ | Docker desktop | `automify.dockerComputer()` | Linux desktop inside a running Docker container |
18
18
 
19
19
  Command use surfaces:
20
20
 
21
- | Surface | Factory | What it does |
22
- | ---------- | ---------------------- | ---------------------------------------------------- |
23
- | CLI | `automify.cli()` | Terminal automation through model-requested commands |
24
- | Docker CLI | `automify.dockerCli()` | Containerized terminal automation with shared files |
21
+ | Surface | Factory | What it does |
22
+ | ---------- | ---------------------- | ----------------------------------------------------- |
23
+ | CLI | `automify.cli()` | Terminal automation through model-requested commands |
24
+ | Docker CLI | `automify.dockerCli()` | Containerized terminal automation with running Docker |
25
25
 
26
26
  OpenAI and Anthropic models are supported, and any other model can be plugged in with a custom provider adapter.
27
27
 
@@ -147,7 +147,7 @@ const cli = automify.cli({
147
147
  await cli.do("Run the tests and summarize failures");
148
148
  ```
149
149
 
150
- Use Docker CLI when command execution should happen inside an isolated container:
150
+ Use Docker CLI when command execution should happen inside an isolated container. Docker must be installed and running before you create the adapter:
151
151
 
152
152
  ```js
153
153
  import { mkdir, mkdtemp, readFile, writeFile } from "node:fs/promises";
@@ -212,7 +212,7 @@ xcode-select --install
212
212
  brew install cmake
213
213
 
214
214
  # Debian/Ubuntu Linux.
215
- sudo apt-get install -y build-essential cmake libxtst-dev libpng++-dev
215
+ sudo apt-get install -y git build-essential cmake pkg-config libx11-dev libxtst-dev libpng++-dev
216
216
 
217
217
  # Fedora Linux.
218
218
  sudo dnf install -y gcc-c++ make cmake libXtst-devel libpng-devel
@@ -221,7 +221,7 @@ sudo dnf install -y gcc-c++ make cmake libXtst-devel libpng-devel
221
221
  sudo pacman -S --needed base-devel cmake libxtst libpng
222
222
  ```
223
223
 
224
- On headless Linux hosts, also install `xvfb` unless you manage `DISPLAY` yourself. On macOS and Windows, `cmake --version` must work in the terminal where you run `npx automify-install-desktop`. On Windows, the VS Code CMake Tools extension is not enough by itself, and Visual Studio 2026 is not currently recognized by the native build chain used by nut.js.
224
+ On Linux, install the full package list before running `npx automify-install-desktop`; the installer checks for command-line build tools but does not verify every native library package. On headless Linux hosts, also install `xvfb` unless you manage `DISPLAY` yourself. On macOS and Windows, `cmake --version` must work in the terminal where you run `npx automify-install-desktop`. On Windows, the VS Code CMake Tools extension is not enough by itself, and Visual Studio 2026 is not currently recognized by the native build chain used by nut.js.
225
225
 
226
226
  ```js
227
227
  import { initAutomify } from "automify";
@@ -246,7 +246,7 @@ try {
246
246
  }
247
247
  ```
248
248
 
249
- For isolated Linux desktop computer use, use Docker. `dockerComputer()` can run from a macOS, Windows, or Linux host with Docker, but the desktop it controls inside the container is Linux. Docker desktop does not use `automify-install-desktop`; it needs Docker and an initial app command:
249
+ For isolated Linux desktop computer use, use Docker. `dockerComputer()` can run from a macOS, Windows, or Linux host with Docker installed and running, but the desktop it controls inside the container is Linux. Docker desktop does not use `automify-install-desktop`; it needs a running Docker daemon and an initial app command:
250
250
 
251
251
  ```js
252
252
  import { initAutomify } from "automify";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "automify",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "AI computer use for browser, CLI, and desktop in Node.js.",
5
5
  "homepage": "https://aldovincenti.github.io/automify",
6
6
  "bugs": {
@@ -132,7 +132,8 @@ function checkBuildPrerequisites() {
132
132
  if (process.platform === "darwin") {
133
133
  console.error("macOS: install Xcode Command Line Tools with `xcode-select --install` and install CMake.");
134
134
  } else if (process.platform === "linux") {
135
- console.error("Linux: install CMake, a C/C++ compiler, libxtst-dev, and libpng++-dev.");
135
+ console.error("Linux: install git, build-essential, cmake, pkg-config, libx11-dev, libxtst-dev, and libpng++-dev.");
136
+ console.error("The Linux installer does not verify every native library package before building.");
136
137
  } else if (process.platform === "win32") {
137
138
  console.error("Windows: install CMake and Visual Studio 2022 C++ Build Tools.");
138
139
  console.error("Make sure the `Desktop development with C++` workload is installed.");
@@ -51,7 +51,7 @@ export const argumentReference = [
51
51
  "logFile"
52
52
  ],
53
53
  notes:
54
- 'Use additionalAptPackages to apt-install Debian packages before commands run. Use preset: "repo" to mount the current workspace at /workspace and allow common repo commands. Use logFile to capture CLI and Docker container events.'
54
+ 'Requires Docker to be installed and running. Use additionalAptPackages to apt-install Debian packages before commands run. Use preset: "repo" to mount the current workspace at /workspace and allow common repo commands. Use logFile to capture CLI and Docker container events.'
55
55
  },
56
56
  {
57
57
  surface: "automify.dockerComputer()",
@@ -66,7 +66,7 @@ export const argumentReference = [
66
66
  "logFile"
67
67
  ],
68
68
  notes:
69
- "Creates a Docker-backed Linux desktop runner. Pass startupCommand or desktop.startupCommand to launch the initial app. Use additionalAptPackages to apt-install extra Debian packages. Use logFile to capture automation and Docker desktop events. Explicit container names are locked per name until close()."
69
+ "Creates a Docker-backed Linux desktop runner and requires Docker to be installed and running. Pass startupCommand or desktop.startupCommand to launch the initial app. Use additionalAptPackages to apt-install extra Debian packages. Use logFile to capture automation and Docker desktop events. Explicit container names are locked per name until close()."
70
70
  },
71
71
  {
72
72
  surface: "automify.localComputer()",
@@ -93,6 +93,6 @@ export const argumentReference = [
93
93
  "logFile"
94
94
  ],
95
95
  notes:
96
- "container controls Docker and resource limits; startupCommand or desktop.startupCommand is required; shared/sharedFiles control host file access. Use additionalAptPackages to apt-install extra Debian packages and logFile to capture Docker desktop events."
96
+ "Requires Docker to be installed and running. container controls Docker and resource limits; startupCommand or desktop.startupCommand is required; shared/sharedFiles control host file access. Use additionalAptPackages to apt-install extra Debian packages and logFile to capture Docker desktop events."
97
97
  }
98
98
  ];
@@ -483,7 +483,7 @@ function localDesktopInstallHelp(platform = process.platform) {
483
483
  return "On Windows, install Visual Studio C++ Build Tools and make sure `cmake --version` works, for example after `winget install Kitware.CMake`.";
484
484
  }
485
485
  if (platform === "linux") {
486
- return "On Linux, install the native build tools for your distro: Debian/Ubuntu need `build-essential cmake libxtst-dev libpng++-dev`; Fedora needs `gcc-c++ make cmake libXtst-devel libpng-devel`; Arch needs `base-devel cmake libxtst libpng`. Headless hosts also need `xvfb` unless DISPLAY is managed externally.";
486
+ return "On Linux, install the native build tools for your distro before running the desktop installer; it does not verify every native library package. Debian/Ubuntu need `git build-essential cmake pkg-config libx11-dev libxtst-dev libpng++-dev`; Fedora needs `gcc-c++ make cmake libXtst-devel libpng-devel`; Arch needs `base-devel cmake libxtst libpng`. Headless hosts also need `xvfb` unless DISPLAY is managed externally.";
487
487
  }
488
488
  return "Install the native build tools and CMake for this OS.";
489
489
  }
@@ -833,15 +833,20 @@ function describePointTransform(x, y, coordinateSpace) {
833
833
 
834
834
  function buildCoordinateSpace(options, screen) {
835
835
  const macOSDisplay = screen.macOSDisplay;
836
+ const environment = screen.environment ?? options.environment ?? defaultDesktopEnvironment();
836
837
  const pixelScale =
837
838
  positiveNumber(options.pixelScale) ??
838
839
  positiveNumber(macOSDisplay?.backingScaleFactor) ??
839
- inferPixelScale(screen, options);
840
+ inferPixelScale({ ...screen, environment }, options);
840
841
  const defaultScale = 1 / pixelScale;
841
- const mouseScaleX = scaleRatio(macOSDisplay?.width, screen.displayWidth) ?? defaultScale;
842
- const mouseScaleY = scaleRatio(macOSDisplay?.height, screen.displayHeight) ?? defaultScale;
843
- const mouseWidth = positiveNumber(macOSDisplay?.width) ?? positiveNumber(screen.displayWidth) * mouseScaleX;
844
- const mouseHeight = positiveNumber(macOSDisplay?.height) ?? positiveNumber(screen.displayHeight) * mouseScaleY;
842
+ const mouseWidth =
843
+ measuredMouseSize("width", { ...screen, environment, macOSDisplay }) ??
844
+ scaledDisplaySize(screen.displayWidth, defaultScale);
845
+ const mouseHeight =
846
+ measuredMouseSize("height", { ...screen, environment, macOSDisplay }) ??
847
+ scaledDisplaySize(screen.displayHeight, defaultScale);
848
+ const mouseScaleX = scaleRatio(mouseWidth, screen.displayWidth) ?? defaultScale;
849
+ const mouseScaleY = scaleRatio(mouseHeight, screen.displayHeight) ?? defaultScale;
845
850
 
846
851
  return {
847
852
  ...screen,
@@ -856,6 +861,20 @@ function buildCoordinateSpace(options, screen) {
856
861
  };
857
862
  }
858
863
 
864
+ function measuredMouseSize(axis, { environment, macOSDisplay, screenWidth, screenHeight }) {
865
+ const macOSValue = positiveNumber(macOSDisplay?.[axis]);
866
+ if (macOSValue) return macOSValue;
867
+ if (environment === "mac") return null;
868
+ return positiveNumber(axis === "width" ? screenWidth : screenHeight);
869
+ }
870
+
871
+ function scaledDisplaySize(size, scale) {
872
+ const numericSize = positiveNumber(size);
873
+ const numericScale = positiveNumber(scale);
874
+ if (!numericSize || !numericScale) return undefined;
875
+ return numericSize * numericScale;
876
+ }
877
+
859
878
  function scaleRatio(target, source) {
860
879
  const numericTarget = positiveNumber(target);
861
880
  const numericSource = positiveNumber(source);
@@ -865,18 +884,29 @@ function scaleRatio(target, source) {
865
884
 
866
885
  function inferPixelScale({ displayWidth, displayHeight, screenWidth, screenHeight }, options = {}) {
867
886
  const environment = options.environment ?? defaultDesktopEnvironment();
868
- if (environment !== "mac") return 1;
869
-
870
887
  const width = positiveNumber(displayWidth) ?? positiveNumber(screenWidth);
871
888
  const height = positiveNumber(displayHeight) ?? positiveNumber(screenHeight);
872
889
  if (!width || !height) return 1;
873
890
 
891
+ if (environment !== "mac") {
892
+ const widthScale = scaleRatio(width, screenWidth);
893
+ const heightScale = scaleRatio(height, screenHeight);
894
+ if (widthScale && heightScale && nearlyEqual(widthScale, heightScale)) {
895
+ return widthScale;
896
+ }
897
+ return 1;
898
+ }
899
+
874
900
  // libnut reports macOS screen size in backing pixels, while CGEvent mouse
875
901
  // coordinates use logical points. Built-in Retina displays are 2x here.
876
902
  if (width >= 2000 || height >= 1400) return 2;
877
903
  return 1;
878
904
  }
879
905
 
906
+ function nearlyEqual(left, right, epsilon = 0.01) {
907
+ return Math.abs(left - right) <= epsilon;
908
+ }
909
+
880
910
  function positiveNumber(value) {
881
911
  const number = Number(value);
882
912
  return Number.isFinite(number) && number > 0 ? number : null;