automify 0.1.9 → 0.1.10
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
|
@@ -120,12 +120,12 @@ const browser = await automify.browser({
|
|
|
120
120
|
});
|
|
121
121
|
|
|
122
122
|
try {
|
|
123
|
-
const run = await browser.do("
|
|
123
|
+
const run = await browser.do("Summarize what you see on the page.", {
|
|
124
124
|
// Optional: structured result shape.
|
|
125
|
-
output: jsonOutput("
|
|
125
|
+
output: jsonOutput("page_summary", { title: "string", summary: "string" })
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
console.log(run.parsed.
|
|
128
|
+
console.log(run.parsed.title, run.parsed.summary);
|
|
129
129
|
} finally {
|
|
130
130
|
await browser.close();
|
|
131
131
|
}
|
|
@@ -208,6 +208,9 @@ winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --override "-
|
|
|
208
208
|
winget install --id Kitware.CMake --exact --source winget
|
|
209
209
|
|
|
210
210
|
# macOS: Xcode Command Line Tools plus CMake on PATH.
|
|
211
|
+
# If Homebrew is not installed, install it first:
|
|
212
|
+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
213
|
+
|
|
211
214
|
xcode-select --install
|
|
212
215
|
brew install cmake
|
|
213
216
|
|
|
@@ -221,7 +224,9 @@ sudo dnf install -y gcc-c++ make cmake libXtst-devel libpng-devel
|
|
|
221
224
|
sudo pacman -S --needed base-devel cmake libxtst libpng
|
|
222
225
|
```
|
|
223
226
|
|
|
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.
|
|
227
|
+
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, install Homebrew first if `brew` is not available, then install CMake with `brew install cmake`. 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.
|
|
228
|
+
|
|
229
|
+
`npx automify-install-desktop` stores the compiled desktop runtime outside `node_modules` in a long-term cache, so normal `npm update` runs do not remove it. If a later `npm install` or `npm update` detects that a previously installed desktop runtime no longer matches the current platform, CPU architecture, Node ABI, or pinned nut.js/libnut revisions, Automify rebuilds it automatically during `postinstall`. Default cache roots are `%LOCALAPPDATA%\automify\desktop-runtime` on Windows, `~/Library/Caches/automify/desktop-runtime` on macOS, and `${XDG_CACHE_HOME:-~/.cache}/automify/desktop-runtime` on Linux. Override with `AUTOMIFY_DESKTOP_RUNTIME_DIR`; disable auto-rebuild with `AUTOMIFY_SKIP_DESKTOP_AUTO_REBUILD=1`.
|
|
225
230
|
|
|
226
231
|
```js
|
|
227
232
|
import { initAutomify } from "automify";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "automify",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
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": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"SECURITY.md"
|
|
37
37
|
],
|
|
38
38
|
"scripts": {
|
|
39
|
-
"postinstall": "node scripts/install-browser.js",
|
|
39
|
+
"postinstall": "node scripts/install-browser.js && node scripts/install-desktop-if-needed.js",
|
|
40
40
|
"install:desktop": "node scripts/install-desktop.js",
|
|
41
41
|
"docs:arguments": "node scripts/generate-argument-reference.js",
|
|
42
42
|
"test": "node --test test/*.test.js",
|
|
@@ -9,6 +9,7 @@ if (process.env.AUTOMIFY_SKIP_BROWSER_INSTALL === "1" || process.env.PLAYWRIGHT_
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
const playwrightCli = join(dirname(require.resolve("playwright")), "cli.js");
|
|
12
|
+
console.log("Automify: installing Playwright browser...");
|
|
12
13
|
const result = spawnSync(process.execPath, [playwrightCli, "install", "chromium"], {
|
|
13
14
|
cwd: process.cwd(),
|
|
14
15
|
stdio: "inherit"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
desktopRuntimeDir,
|
|
9
|
+
desktopRuntimeIsInstalled,
|
|
10
|
+
desktopRuntimeKey,
|
|
11
|
+
findDesktopRuntimeManifests
|
|
12
|
+
} from "../src/lib/desktop-runtime.js";
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const root = resolve(__dirname, "..");
|
|
16
|
+
|
|
17
|
+
if (process.env.AUTOMIFY_SKIP_DESKTOP_INSTALL === "1" || process.env.AUTOMIFY_SKIP_DESKTOP_AUTO_REBUILD === "1") {
|
|
18
|
+
process.exit(0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (desktopRuntimeIsInstalled()) {
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const existingManifests = findDesktopRuntimeManifests();
|
|
26
|
+
const legacyNodeModulesRuntime = existsSync(join(root, "node_modules", "@nut-tree", "nut-js", "package.json"));
|
|
27
|
+
|
|
28
|
+
if (existingManifests.length === 0 && !legacyNodeModulesRuntime) {
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log("Automify desktop runtime was previously installed but is not compatible with this environment.");
|
|
33
|
+
console.log(`Rebuilding desktop runtime cache: ${desktopRuntimeKey()}`);
|
|
34
|
+
console.log(`Runtime directory: ${desktopRuntimeDir()}`);
|
|
35
|
+
|
|
36
|
+
const result = spawnSync(process.execPath, [join(__dirname, "install-desktop.js")], {
|
|
37
|
+
cwd: root,
|
|
38
|
+
env: process.env,
|
|
39
|
+
stdio: "inherit"
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
process.exit(result.status ?? 1);
|
|
@@ -4,6 +4,15 @@ import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } fr
|
|
|
4
4
|
import { dirname, join, resolve, sep } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
|
|
7
|
+
import {
|
|
8
|
+
DESKTOP_RUNTIME_MANIFEST,
|
|
9
|
+
desktopRuntimeDir,
|
|
10
|
+
desktopRuntimeKey,
|
|
11
|
+
desktopRuntimeManifest,
|
|
12
|
+
desktopRuntimeNodeModules,
|
|
13
|
+
desktopRuntimeRefs
|
|
14
|
+
} from "../src/lib/desktop-runtime.js";
|
|
15
|
+
|
|
7
16
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
17
|
const root = resolve(__dirname, "..");
|
|
9
18
|
const buildRoot = process.env.AUTOMIFY_DESKTOP_BUILD_DIR
|
|
@@ -12,12 +21,10 @@ const buildRoot = process.env.AUTOMIFY_DESKTOP_BUILD_DIR
|
|
|
12
21
|
const nutSource = join(buildRoot, "nut.js");
|
|
13
22
|
const libnutSource = join(buildRoot, "libnut-core");
|
|
14
23
|
const macPermissionsSource = join(buildRoot, "node-mac-permissions");
|
|
15
|
-
const refs =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
};
|
|
20
|
-
const nodeModules = join(root, "node_modules");
|
|
24
|
+
const refs = desktopRuntimeRefs();
|
|
25
|
+
const runtimeDir = desktopRuntimeDir();
|
|
26
|
+
const runtimeNodeModules = desktopRuntimeNodeModules();
|
|
27
|
+
const nodeModules = runtimeNodeModules;
|
|
21
28
|
const nutScope = join(nodeModules, "@nut-tree");
|
|
22
29
|
const platformPackageName = `@nut-tree/libnut-${process.platform}`;
|
|
23
30
|
const platformPackageDir = join(nutScope, `libnut-${process.platform}`);
|
|
@@ -27,6 +34,8 @@ const runtimeDependencies = ["jimp@1.6.1", "node-abort-controller@3.1.1", "clipb
|
|
|
27
34
|
|
|
28
35
|
console.log("Building official nut.js from source.");
|
|
29
36
|
console.log(`Build directory: ${buildRoot}`);
|
|
37
|
+
console.log(`Runtime directory: ${runtimeDir}`);
|
|
38
|
+
console.log(`Runtime key: ${desktopRuntimeKey()}`);
|
|
30
39
|
console.log(`nut.js ref: ${refs.nut}`);
|
|
31
40
|
console.log(`libnut-core ref: ${refs.libnutCore}`);
|
|
32
41
|
if (process.platform === "darwin") {
|
|
@@ -36,6 +45,8 @@ if (process.platform === "darwin") {
|
|
|
36
45
|
checkBuildPrerequisites();
|
|
37
46
|
|
|
38
47
|
mkdirSync(buildRoot, { recursive: true });
|
|
48
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
49
|
+
writeRuntimePackageJson();
|
|
39
50
|
cloneOrPull("https://github.com/nut-tree/libnut-core.git", libnutSource, refs.libnutCore);
|
|
40
51
|
cloneOrPull("https://github.com/nut-tree/nut.js.git", nutSource, refs.nut);
|
|
41
52
|
if (process.platform === "darwin") {
|
|
@@ -69,7 +80,7 @@ writeLibnutImportBridge();
|
|
|
69
80
|
runPnpm(["--filter", "@nut-tree/nut-js", "run", "compile"], { cwd: nutSource });
|
|
70
81
|
patchNutJimpCompatibility();
|
|
71
82
|
|
|
72
|
-
run("npm", ["install", "--no-save", ...runtimeDependencies], { cwd:
|
|
83
|
+
run("npm", ["install", "--no-save", ...runtimeDependencies], { cwd: runtimeDir });
|
|
73
84
|
|
|
74
85
|
installWorkspacePackage(join(nutSource, "core", "shared"), join(nutScope, "shared"));
|
|
75
86
|
installWorkspacePackage(join(nutSource, "core", "provider-interfaces"), join(nutScope, "provider-interfaces"));
|
|
@@ -81,9 +92,20 @@ if (process.platform === "darwin") {
|
|
|
81
92
|
installWorkspacePackage(macPermissionsSource, macPermissionsPackageDir);
|
|
82
93
|
}
|
|
83
94
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
writeRuntimeManifest();
|
|
96
|
+
run(
|
|
97
|
+
"node",
|
|
98
|
+
[
|
|
99
|
+
"-e",
|
|
100
|
+
`const { createRequire } = require("node:module");
|
|
101
|
+
const { join } = require("node:path");
|
|
102
|
+
const runtimeDir = process.argv[1];
|
|
103
|
+
createRequire(join(runtimeDir, "automify-desktop-runtime.cjs"))("@nut-tree/nut-js");
|
|
104
|
+
console.log("nut.js source build import ok");`,
|
|
105
|
+
runtimeDir
|
|
106
|
+
],
|
|
107
|
+
{ cwd: root }
|
|
108
|
+
);
|
|
87
109
|
|
|
88
110
|
function cloneOrPull(repo, target, ref) {
|
|
89
111
|
if (existsSync(join(target, ".git"))) {
|
|
@@ -160,22 +182,26 @@ function resolveCommand(command) {
|
|
|
160
182
|
function commandCandidates(command) {
|
|
161
183
|
const candidates = [];
|
|
162
184
|
|
|
185
|
+
const npmCli = npmCliCandidate(command);
|
|
186
|
+
if (npmCli) candidates.push(npmCli);
|
|
187
|
+
|
|
163
188
|
if (process.platform === "win32" && ["npm", "npx"].includes(command)) {
|
|
164
189
|
candidates.push({ command: `${command}.cmd`, args: [] });
|
|
165
190
|
}
|
|
166
191
|
|
|
167
|
-
const npmCli = npmCliCandidate(command);
|
|
168
|
-
if (npmCli) candidates.push(npmCli);
|
|
169
|
-
|
|
170
192
|
candidates.push({ command, args: [] });
|
|
171
193
|
return candidates;
|
|
172
194
|
}
|
|
173
195
|
|
|
174
196
|
function npmCliCandidate(command) {
|
|
175
|
-
if (!["npm", "npx"].includes(command)
|
|
176
|
-
|
|
197
|
+
if (!["npm", "npx"].includes(command)) return null;
|
|
198
|
+
|
|
199
|
+
const npmExecPath =
|
|
200
|
+
process.env.npm_execpath ?? join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
|
|
201
|
+
if (!existsSync(npmExecPath)) return null;
|
|
202
|
+
if (command === "npm") return { command: process.execPath, args: [npmExecPath] };
|
|
177
203
|
|
|
178
|
-
const npxExecPath = join(dirname(
|
|
204
|
+
const npxExecPath = join(dirname(npmExecPath), "npx-cli.js");
|
|
179
205
|
if (!existsSync(npxExecPath)) return null;
|
|
180
206
|
return { command: process.execPath, args: [npxExecPath] };
|
|
181
207
|
}
|
|
@@ -404,6 +430,35 @@ function installWorkspacePackage(source, target) {
|
|
|
404
430
|
});
|
|
405
431
|
}
|
|
406
432
|
|
|
433
|
+
function writeRuntimePackageJson() {
|
|
434
|
+
writeText(
|
|
435
|
+
join(runtimeDir, "package.json"),
|
|
436
|
+
`${JSON.stringify(
|
|
437
|
+
{
|
|
438
|
+
private: true,
|
|
439
|
+
name: "automify-desktop-runtime",
|
|
440
|
+
description: "Persistent native runtime cache for Automify local desktop support."
|
|
441
|
+
},
|
|
442
|
+
null,
|
|
443
|
+
2
|
|
444
|
+
)}\n`
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function writeRuntimeManifest() {
|
|
449
|
+
writeText(
|
|
450
|
+
join(runtimeDir, DESKTOP_RUNTIME_MANIFEST),
|
|
451
|
+
`${JSON.stringify(
|
|
452
|
+
{
|
|
453
|
+
...desktopRuntimeManifest(),
|
|
454
|
+
createdAt: new Date().toISOString()
|
|
455
|
+
},
|
|
456
|
+
null,
|
|
457
|
+
2
|
|
458
|
+
)}\n`
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
|
|
407
462
|
function run(command, args, options = {}) {
|
|
408
463
|
const result = runResolvedCommand(command, args, {
|
|
409
464
|
cwd: options.cwd ?? root,
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
|
|
5
|
+
export const DESKTOP_RUNTIME_PACKAGE = "@nut-tree/nut-js";
|
|
6
|
+
export const DESKTOP_RUNTIME_MANIFEST = "automify-desktop-runtime.json";
|
|
7
|
+
|
|
8
|
+
export function desktopRuntimeRefs(env = process.env) {
|
|
9
|
+
return {
|
|
10
|
+
nut: env.AUTOMIFY_DESKTOP_NUT_REF ?? "e413fa1f19a19c4631812e4e1eaf47aa732b5cbe",
|
|
11
|
+
libnutCore: env.AUTOMIFY_DESKTOP_LIBNUT_CORE_REF ?? "6bbe5825f1123bcd740117ca932c8b1c6cffb48c",
|
|
12
|
+
macPermissions: env.AUTOMIFY_DESKTOP_MAC_PERMISSIONS_REF ?? "6b6ddee993ddce5071b637e42f6ee1434150d0bb"
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function desktopRuntimeCompatibility(env = process.env) {
|
|
17
|
+
const refs = desktopRuntimeRefs(env);
|
|
18
|
+
return {
|
|
19
|
+
platform: process.platform,
|
|
20
|
+
arch: process.arch,
|
|
21
|
+
nodeAbi: process.versions.modules,
|
|
22
|
+
nutRef: refs.nut,
|
|
23
|
+
libnutCoreRef: refs.libnutCore,
|
|
24
|
+
macPermissionsRef: process.platform === "darwin" ? refs.macPermissions : undefined
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function desktopRuntimeKey(compatibility = desktopRuntimeCompatibility()) {
|
|
29
|
+
return [
|
|
30
|
+
compatibility.platform,
|
|
31
|
+
compatibility.arch,
|
|
32
|
+
`node-${compatibility.nodeAbi}`,
|
|
33
|
+
`nut-${shortRef(compatibility.nutRef)}`,
|
|
34
|
+
`libnut-${shortRef(compatibility.libnutCoreRef)}`,
|
|
35
|
+
compatibility.macPermissionsRef ? `macperms-${shortRef(compatibility.macPermissionsRef)}` : null
|
|
36
|
+
]
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
.join("-");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function defaultDesktopRuntimeRoot(env = process.env) {
|
|
42
|
+
if (env.AUTOMIFY_DESKTOP_RUNTIME_DIR) {
|
|
43
|
+
return resolve(env.AUTOMIFY_DESKTOP_RUNTIME_DIR);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (process.platform === "win32") {
|
|
47
|
+
return join(env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local"), "automify", "desktop-runtime");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (process.platform === "darwin") {
|
|
51
|
+
return join(homedir(), "Library", "Caches", "automify", "desktop-runtime");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return join(env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "automify", "desktop-runtime");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function desktopRuntimeDir(env = process.env) {
|
|
58
|
+
return join(defaultDesktopRuntimeRoot(env), desktopRuntimeKey(desktopRuntimeCompatibility(env)));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function desktopRuntimeNodeModules(env = process.env) {
|
|
62
|
+
return join(desktopRuntimeDir(env), "node_modules");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function desktopRuntimePackageJsonPath(env = process.env) {
|
|
66
|
+
return join(desktopRuntimeNodeModules(env), "@nut-tree", "nut-js", "package.json");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function desktopRuntimeManifestPath(env = process.env) {
|
|
70
|
+
return join(desktopRuntimeDir(env), DESKTOP_RUNTIME_MANIFEST);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function desktopRuntimeManifest(env = process.env) {
|
|
74
|
+
return {
|
|
75
|
+
version: 1,
|
|
76
|
+
package: DESKTOP_RUNTIME_PACKAGE,
|
|
77
|
+
runtimeDir: desktopRuntimeDir(env),
|
|
78
|
+
compatibility: desktopRuntimeCompatibility(env)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function readDesktopRuntimeManifest(env = process.env) {
|
|
83
|
+
const path = desktopRuntimeManifestPath(env);
|
|
84
|
+
if (!existsSync(path)) return null;
|
|
85
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function findDesktopRuntimeManifests(env = process.env) {
|
|
89
|
+
const root = defaultDesktopRuntimeRoot(env);
|
|
90
|
+
if (!existsSync(root)) return [];
|
|
91
|
+
|
|
92
|
+
return readdirSync(root, { withFileTypes: true })
|
|
93
|
+
.filter((entry) => entry.isDirectory())
|
|
94
|
+
.map((entry) => {
|
|
95
|
+
const runtimeDir = join(root, entry.name);
|
|
96
|
+
const manifestPath = join(runtimeDir, DESKTOP_RUNTIME_MANIFEST);
|
|
97
|
+
if (!existsSync(manifestPath)) return null;
|
|
98
|
+
try {
|
|
99
|
+
return {
|
|
100
|
+
runtimeDir,
|
|
101
|
+
manifestPath,
|
|
102
|
+
manifest: JSON.parse(readFileSync(manifestPath, "utf8"))
|
|
103
|
+
};
|
|
104
|
+
} catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
.filter(Boolean);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function desktopRuntimeIsInstalled(env = process.env) {
|
|
112
|
+
const manifest = readDesktopRuntimeManifest(env);
|
|
113
|
+
return desktopRuntimeManifestMatches(manifest, env) && existsSync(desktopRuntimePackageJsonPath(env));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function desktopRuntimeManifestMatches(manifest, env = process.env) {
|
|
117
|
+
if (!manifest || manifest.version !== 1 || manifest.package !== DESKTOP_RUNTIME_PACKAGE) return false;
|
|
118
|
+
|
|
119
|
+
const expected = desktopRuntimeCompatibility(env);
|
|
120
|
+
const actual = manifest.compatibility ?? {};
|
|
121
|
+
return (
|
|
122
|
+
actual.platform === expected.platform &&
|
|
123
|
+
actual.arch === expected.arch &&
|
|
124
|
+
actual.nodeAbi === expected.nodeAbi &&
|
|
125
|
+
actual.nutRef === expected.nutRef &&
|
|
126
|
+
actual.libnutCoreRef === expected.libnutCoreRef &&
|
|
127
|
+
actual.macPermissionsRef === expected.macPermissionsRef
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function shortRef(ref) {
|
|
132
|
+
return String(ref ?? "unknown")
|
|
133
|
+
.replace(/[^a-zA-Z0-9._-]/g, "_")
|
|
134
|
+
.slice(0, 12);
|
|
135
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
1
3
|
import { readFile, unlink } from "node:fs/promises";
|
|
2
4
|
import { execFile, spawn } from "node:child_process";
|
|
3
5
|
import { tmpdir } from "node:os";
|
|
@@ -8,6 +10,12 @@ import { promisify } from "node:util";
|
|
|
8
10
|
import { AutomifyError } from "./errors.js";
|
|
9
11
|
import { acquireAdapterLock } from "./adapter-locks.js";
|
|
10
12
|
import { assertKnownOptions, normalizeLogFile, writeDebugLogFile } from "./runtime.js";
|
|
13
|
+
import {
|
|
14
|
+
DESKTOP_RUNTIME_PACKAGE,
|
|
15
|
+
desktopRuntimeDir,
|
|
16
|
+
desktopRuntimeManifestMatches,
|
|
17
|
+
desktopRuntimeManifestPath
|
|
18
|
+
} from "./desktop-runtime.js";
|
|
11
19
|
|
|
12
20
|
const execFileAsync = promisify(execFile);
|
|
13
21
|
const LOCAL_DESKTOP_OPTION_KEYS = new Set([
|
|
@@ -448,16 +456,39 @@ async function saveNutImageObject(nut, image, options = {}) {
|
|
|
448
456
|
}
|
|
449
457
|
|
|
450
458
|
async function importNut() {
|
|
459
|
+
let runtimeError;
|
|
451
460
|
try {
|
|
452
|
-
|
|
461
|
+
const runtimeNut = importNutFromDesktopRuntime();
|
|
462
|
+
if (runtimeNut) return runtimeNut;
|
|
453
463
|
} catch (error) {
|
|
464
|
+
runtimeError = error;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
try {
|
|
468
|
+
return await import(DESKTOP_RUNTIME_PACKAGE);
|
|
469
|
+
} catch (error) {
|
|
470
|
+
const runtimeSuffix = runtimeError ? ` Cached desktop runtime import failed: ${runtimeError.message}` : "";
|
|
454
471
|
throw new AutomifyError(
|
|
455
|
-
`createLocalDesktopComputer requires the local desktop adapter dependency built from source. ${localDesktopInstallHelp()} After the OS prerequisites are available, run: npx automify-install-desktop`,
|
|
472
|
+
`createLocalDesktopComputer requires the local desktop adapter dependency built from source. ${localDesktopInstallHelp()} After the OS prerequisites are available, run: npx automify-install-desktop.${runtimeSuffix}`,
|
|
456
473
|
{ cause: error }
|
|
457
474
|
);
|
|
458
475
|
}
|
|
459
476
|
}
|
|
460
477
|
|
|
478
|
+
function importNutFromDesktopRuntime() {
|
|
479
|
+
const manifestPath = desktopRuntimeManifestPath();
|
|
480
|
+
let manifest;
|
|
481
|
+
try {
|
|
482
|
+
manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
483
|
+
} catch {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
if (!desktopRuntimeManifestMatches(manifest)) return null;
|
|
487
|
+
|
|
488
|
+
const runtimeRequire = createRequire(join(desktopRuntimeDir(), "automify-desktop-runtime.cjs"));
|
|
489
|
+
return runtimeRequire(DESKTOP_RUNTIME_PACKAGE);
|
|
490
|
+
}
|
|
491
|
+
|
|
461
492
|
function normalizeLocalDesktopEnvironment(environment) {
|
|
462
493
|
if (environment == null) return undefined;
|
|
463
494
|
if (typeof environment !== "string" || environment.trim() === "") {
|