hrctl 0.1.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/bin/hr.js +101 -0
- package/package.json +28 -0
package/bin/hr.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require("node:child_process");
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
|
|
6
|
+
const BINARY_NAME = process.platform === "win32" ? "hr.exe" : "hr";
|
|
7
|
+
|
|
8
|
+
const PLATFORM_PACKAGES = {
|
|
9
|
+
"linux x64 glibc": "harness-router-linux-x64",
|
|
10
|
+
"linux x64 musl": "harness-router-linux-x64-musl",
|
|
11
|
+
"linux arm64 glibc": "harness-router-linux-arm64",
|
|
12
|
+
"linux arm64 musl": "harness-router-linux-arm64-musl",
|
|
13
|
+
"darwin x64": "harness-router-darwin-x64",
|
|
14
|
+
"darwin arm64": "harness-router-darwin-arm64",
|
|
15
|
+
"win32 x64": "harness-router-win32-x64",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
function isMusl() {
|
|
19
|
+
let report = null;
|
|
20
|
+
try {
|
|
21
|
+
report = typeof process.report?.getReport === "function" ? process.report.getReport() : null;
|
|
22
|
+
} catch {
|
|
23
|
+
report = null;
|
|
24
|
+
}
|
|
25
|
+
if (report && report.header && report.header.glibcVersionRuntime) return false;
|
|
26
|
+
if (report && Array.isArray(report.sharedObjects)) {
|
|
27
|
+
if (report.sharedObjects.some((o) => /\/(?:libc\.musl-|ld-musl-)/.test(o))) return true;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const { execSync } = require("node:child_process");
|
|
31
|
+
const out = execSync("ldd --version 2>&1 || true", { encoding: "utf8" });
|
|
32
|
+
if (out.includes("musl")) return true;
|
|
33
|
+
if (out.includes("GNU C Library") || out.includes("glibc")) return false;
|
|
34
|
+
} catch {
|
|
35
|
+
/* ignore */
|
|
36
|
+
}
|
|
37
|
+
return false; // assume glibc
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function platformKey() {
|
|
41
|
+
const { platform, arch } = process;
|
|
42
|
+
if (platform === "linux") return `linux ${arch} ${isMusl() ? "musl" : "glibc"}`;
|
|
43
|
+
return `${platform} ${arch}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function fail(msg) {
|
|
47
|
+
console.error(`\n[harness-router] ${msg}\n`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function resolveBinaryPath() {
|
|
52
|
+
const override = process.env.HR_BINARY_PATH;
|
|
53
|
+
if (override) {
|
|
54
|
+
if (fs.existsSync(override)) return override;
|
|
55
|
+
console.warn(`[harness-router] HR_BINARY_PATH is set to "${override}" but that path does not exist — ignoring it.`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const key = platformKey();
|
|
59
|
+
const pkg = PLATFORM_PACKAGES[key];
|
|
60
|
+
if (!pkg) {
|
|
61
|
+
fail(`no prebuilt binary for your platform (${key}).\n` + `Supported: ${Object.keys(PLATFORM_PACKAGES).join(", ")}.`);
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
return require.resolve(`${pkg}/${BINARY_NAME}`);
|
|
65
|
+
} catch {
|
|
66
|
+
fail(
|
|
67
|
+
`could not find the binary package "${pkg}" for your platform (${key}).\n\n` +
|
|
68
|
+
`It should have installed automatically as an optional dependency. Likely causes:\n` +
|
|
69
|
+
` - install ran with --no-optional / --omit=optional\n` +
|
|
70
|
+
` - node_modules was built on a different OS/arch and copied here\n` +
|
|
71
|
+
` - the optional dependency failed to download\n\n` +
|
|
72
|
+
`Fix: reinstall on this machine: npm install -g harness-router`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function run() {
|
|
78
|
+
const binPath = resolveBinaryPath();
|
|
79
|
+
const child = spawn(binPath, process.argv.slice(2), { stdio: "inherit", windowsHide: false });
|
|
80
|
+
|
|
81
|
+
const signals = ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT"];
|
|
82
|
+
const forward = (sig) => {
|
|
83
|
+
if (!child.killed) {
|
|
84
|
+
try {
|
|
85
|
+
child.kill(sig);
|
|
86
|
+
} catch {
|
|
87
|
+
/* ignore */
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
for (const sig of signals) process.on(sig, () => forward(sig));
|
|
92
|
+
|
|
93
|
+
child.on("error", (err) => fail(`failed to launch ${binPath}:\n${err.message}`));
|
|
94
|
+
child.on("exit", (code, signal) => {
|
|
95
|
+
for (const sig of signals) process.removeAllListeners(sig);
|
|
96
|
+
if (signal) process.kill(process.pid, signal);
|
|
97
|
+
else process.exit(code == null ? 1 : code);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
run();
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hrctl",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "harness-router CLI (hr) — gateway-agnostic control plane for agent harnesses.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/alfin-efendy/herness-router.git"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": ">=18"
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"hr": "bin/hr.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"bin/hr.js"
|
|
18
|
+
],
|
|
19
|
+
"optionalDependencies": {
|
|
20
|
+
"harness-router-linux-x64": "0.1.0",
|
|
21
|
+
"harness-router-linux-arm64": "0.1.0",
|
|
22
|
+
"harness-router-linux-x64-musl": "0.1.0",
|
|
23
|
+
"harness-router-linux-arm64-musl": "0.1.0",
|
|
24
|
+
"harness-router-darwin-x64": "0.1.0",
|
|
25
|
+
"harness-router-darwin-arm64": "0.1.0",
|
|
26
|
+
"harness-router-win32-x64": "0.1.0"
|
|
27
|
+
}
|
|
28
|
+
}
|