@metaphi-ai/hum 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/dist/cli.mjs +129 -59
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -84524,7 +84524,7 @@ import net from "node:net";
|
|
|
84524
84524
|
import os4 from "node:os";
|
|
84525
84525
|
import path2 from "node:path";
|
|
84526
84526
|
import crypto from "node:crypto";
|
|
84527
|
-
import { spawn } from "node:child_process";
|
|
84527
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
84528
84528
|
var runDir = () => path2.join(process.env.HUM_HOME || path2.join(os4.homedir(), ".hum"), "run");
|
|
84529
84529
|
var readRun = (id) => {
|
|
84530
84530
|
try {
|
|
@@ -84535,74 +84535,144 @@ var readRun = (id) => {
|
|
|
84535
84535
|
};
|
|
84536
84536
|
var EngineError = class extends Error {
|
|
84537
84537
|
};
|
|
84538
|
-
var
|
|
84539
|
-
|
|
84540
|
-
|
|
84541
|
-
|
|
84542
|
-
|
|
84543
|
-
|
|
84544
|
-
|
|
84545
|
-
|
|
84546
|
-
|
|
84538
|
+
var win = process.platform === "win32";
|
|
84539
|
+
var exists = (p) => {
|
|
84540
|
+
try {
|
|
84541
|
+
fs3.accessSync(p);
|
|
84542
|
+
return true;
|
|
84543
|
+
} catch {
|
|
84544
|
+
return false;
|
|
84545
|
+
}
|
|
84546
|
+
};
|
|
84547
|
+
function uvToolDirs() {
|
|
84548
|
+
const dirs = [];
|
|
84549
|
+
if (process.env.UV_TOOL_DIR) dirs.push(process.env.UV_TOOL_DIR);
|
|
84550
|
+
if (win) {
|
|
84551
|
+
for (const base of [process.env.APPDATA, process.env.LOCALAPPDATA]) if (base) dirs.push(path2.join(base, "uv", "tools"));
|
|
84552
|
+
} else dirs.push(path2.join(process.env.XDG_DATA_HOME || path2.join(os4.homedir(), ".local", "share"), "uv", "tools"));
|
|
84553
|
+
if (!dirs.some(exists)) {
|
|
84554
|
+
for (const uv of ["uv", path2.join(os4.homedir(), ".local", "bin", win ? "uv.exe" : "uv")]) {
|
|
84555
|
+
try {
|
|
84556
|
+
const r = spawnSync(uv, ["tool", "dir"], { encoding: "utf8", windowsHide: true });
|
|
84557
|
+
if (r.status === 0 && r.stdout.trim()) {
|
|
84558
|
+
dirs.push(r.stdout.trim());
|
|
84559
|
+
break;
|
|
84560
|
+
}
|
|
84561
|
+
} catch {
|
|
84562
|
+
}
|
|
84563
|
+
}
|
|
84564
|
+
}
|
|
84565
|
+
return dirs;
|
|
84566
|
+
}
|
|
84567
|
+
function enginePython(dirs = uvToolDirs()) {
|
|
84568
|
+
for (const dir of dirs) for (const name of ["hum-cli", "hum"]) {
|
|
84569
|
+
const py = win ? path2.join(dir, name, "Scripts", "python.exe") : path2.join(dir, name, "bin", "python");
|
|
84570
|
+
if (exists(py)) return py;
|
|
84571
|
+
}
|
|
84572
|
+
return null;
|
|
84573
|
+
}
|
|
84574
|
+
function engineCandidates(env3 = process.env) {
|
|
84575
|
+
const out = [];
|
|
84576
|
+
if (env3.HUM_ENGINE) {
|
|
84577
|
+
const [bin, ...args2] = env3.HUM_ENGINE.split(" ");
|
|
84578
|
+
out.push({ bin, args: args2, where: "HUM_ENGINE" });
|
|
84579
|
+
}
|
|
84580
|
+
const py = enginePython();
|
|
84581
|
+
if (py) out.push({ bin: py, args: ["-m", "hum.cli", "engine"], where: "the engine's interpreter" });
|
|
84582
|
+
out.push({ bin: "hum-engine", args: [], where: "PATH" });
|
|
84583
|
+
out.push({ bin: path2.join(os4.homedir(), ".local", "bin", win ? "hum-engine.exe" : "hum-engine"), args: [], where: "uv's bin dir" });
|
|
84584
|
+
return out;
|
|
84585
|
+
}
|
|
84586
|
+
function startFailure(failures) {
|
|
84587
|
+
const refused = failures.find((f) => f.error && f.error.code !== "ENOENT");
|
|
84588
|
+
if (!refused) {
|
|
84589
|
+
return "Hum's engine is not installed. Run: uv tool install hum-cli (or set HUM_ENGINE to the command that starts it)";
|
|
84590
|
+
}
|
|
84591
|
+
const what = refused.error.code || refused.error.message;
|
|
84592
|
+
const lines = [
|
|
84593
|
+
`Hum's engine is installed (${refused.bin}) but this machine would not start it: ${what}.`
|
|
84594
|
+
];
|
|
84595
|
+
if (win) {
|
|
84596
|
+
lines.push("On a managed Windows machine that is usually Device Guard / WDAC refusing an executable it does not know.");
|
|
84597
|
+
lines.push(`To see the policy's own message, run: "${refused.bin}" --help`);
|
|
84598
|
+
const dir = uvToolDirs()[0];
|
|
84599
|
+
lines.push(`If uv's environment is elsewhere, point Hum at its interpreter: set HUM_ENGINE=${path2.join(dir || "<uv tool dir>", "hum-cli", "Scripts", "python.exe")} -m hum.cli engine`);
|
|
84600
|
+
} else {
|
|
84601
|
+
lines.push('Set HUM_ENGINE to a command that starts it, e.g. HUM_ENGINE="python -m hum.cli engine"');
|
|
84602
|
+
}
|
|
84603
|
+
return lines.join("\n");
|
|
84604
|
+
}
|
|
84605
|
+
function attempt({ bin, args: args2 }, cwd2, { task, images, resume }) {
|
|
84547
84606
|
return new Promise((resolve, reject) => {
|
|
84548
|
-
const
|
|
84549
|
-
|
|
84550
|
-
|
|
84551
|
-
|
|
84552
|
-
|
|
84553
|
-
|
|
84607
|
+
const runId = crypto.randomBytes(6).toString("hex");
|
|
84608
|
+
fs3.mkdirSync(runDir(), { recursive: true });
|
|
84609
|
+
const logPath = path2.join(runDir(), `${runId}.log`);
|
|
84610
|
+
const log = fs3.openSync(logPath, "a");
|
|
84611
|
+
const argv = [...args2, "-C", cwd2, "--run-id", runId];
|
|
84612
|
+
if (task) argv.push("--task", task);
|
|
84613
|
+
for (const p of images) argv.push("--image", p);
|
|
84614
|
+
if (resume) argv.push("--resume", resume);
|
|
84615
|
+
let settled = false;
|
|
84616
|
+
const settle = (fn) => {
|
|
84617
|
+
if (!settled) {
|
|
84618
|
+
settled = true;
|
|
84619
|
+
fn();
|
|
84620
|
+
}
|
|
84621
|
+
};
|
|
84622
|
+
let child;
|
|
84623
|
+
try {
|
|
84624
|
+
child = spawn(bin, argv, { stdio: ["ignore", log, log], detached: true, windowsHide: true });
|
|
84625
|
+
} catch (e) {
|
|
84626
|
+
fs3.closeSync(log);
|
|
84627
|
+
reject({ spawn: e });
|
|
84628
|
+
return;
|
|
84629
|
+
}
|
|
84630
|
+
fs3.closeSync(log);
|
|
84631
|
+
let died = false;
|
|
84632
|
+
child.on("error", (e) => settle(() => reject({ spawn: e })));
|
|
84633
|
+
child.on("exit", () => {
|
|
84634
|
+
died = true;
|
|
84635
|
+
});
|
|
84636
|
+
const t0 = Date.now();
|
|
84637
|
+
const poll = () => {
|
|
84638
|
+
if (settled) return;
|
|
84639
|
+
const rec = readRun(runId);
|
|
84640
|
+
if (rec && rec.port) {
|
|
84641
|
+
child.unref();
|
|
84642
|
+
settle(() => resolve(rec));
|
|
84554
84643
|
return;
|
|
84555
84644
|
}
|
|
84556
|
-
if (!
|
|
84557
|
-
|
|
84645
|
+
if (died && !rec) {
|
|
84646
|
+
settle(() => reject({ died: logPath }));
|
|
84558
84647
|
return;
|
|
84559
84648
|
}
|
|
84560
|
-
|
|
84561
|
-
|
|
84562
|
-
const log = fs3.openSync(path2.join(runDir(), `${runId}.log`), "a");
|
|
84563
|
-
const [bin, ...rest] = cmd.split(" ");
|
|
84564
|
-
const args2 = [...rest, "-C", cwd2, "--run-id", runId];
|
|
84565
|
-
if (task) args2.push("--task", task);
|
|
84566
|
-
for (const p of images) args2.push("--image", p);
|
|
84567
|
-
if (resume) args2.push("--resume", resume);
|
|
84568
|
-
let child;
|
|
84569
|
-
try {
|
|
84570
|
-
child = spawn(bin, args2, { stdio: ["ignore", log, log], detached: true, windowsHide: true });
|
|
84571
|
-
} catch {
|
|
84572
|
-
tryNext(i + 1);
|
|
84649
|
+
if (Date.now() - t0 > 25e3) {
|
|
84650
|
+
settle(() => reject({ timeout: true }));
|
|
84573
84651
|
return;
|
|
84574
84652
|
}
|
|
84575
|
-
|
|
84576
|
-
child.on("error", () => {
|
|
84577
|
-
failed = true;
|
|
84578
|
-
tryNext(i + 1);
|
|
84579
|
-
});
|
|
84580
|
-
child.on("exit", () => {
|
|
84581
|
-
failed = true;
|
|
84582
|
-
});
|
|
84583
|
-
const t0 = Date.now();
|
|
84584
|
-
const poll = () => {
|
|
84585
|
-
const rec = readRun(runId);
|
|
84586
|
-
if (rec && rec.port) {
|
|
84587
|
-
child.unref();
|
|
84588
|
-
resolve(rec);
|
|
84589
|
-
return;
|
|
84590
|
-
}
|
|
84591
|
-
if (failed && !rec) {
|
|
84592
|
-
reject(new EngineError(`the engine did not start (see ${path2.join(runDir(), `${runId}.log`)})`));
|
|
84593
|
-
return;
|
|
84594
|
-
}
|
|
84595
|
-
if (Date.now() - t0 > 25e3) {
|
|
84596
|
-
reject(new EngineError("the engine did not start in time"));
|
|
84597
|
-
return;
|
|
84598
|
-
}
|
|
84599
|
-
setTimeout(poll, 50);
|
|
84600
|
-
};
|
|
84601
|
-
poll();
|
|
84653
|
+
setTimeout(poll, 50);
|
|
84602
84654
|
};
|
|
84603
|
-
|
|
84655
|
+
poll();
|
|
84604
84656
|
});
|
|
84605
84657
|
}
|
|
84658
|
+
async function spawnEngine(cwd2, { task = null, images = [], resume = null, candidates = engineCandidates() } = {}) {
|
|
84659
|
+
const failures = [];
|
|
84660
|
+
for (const cand of candidates) {
|
|
84661
|
+
if (!cand.bin) continue;
|
|
84662
|
+
try {
|
|
84663
|
+
return await attempt(cand, cwd2, { task, images, resume });
|
|
84664
|
+
} catch (f) {
|
|
84665
|
+
if (f && f.spawn) {
|
|
84666
|
+
failures.push({ ...cand, error: f.spawn });
|
|
84667
|
+
continue;
|
|
84668
|
+
}
|
|
84669
|
+
if (f && f.died) throw new EngineError(`the engine did not start (see ${f.died})`);
|
|
84670
|
+
if (f && f.timeout) throw new EngineError("the engine did not start in time");
|
|
84671
|
+
throw f;
|
|
84672
|
+
}
|
|
84673
|
+
}
|
|
84674
|
+
throw new EngineError(startFailure(failures));
|
|
84675
|
+
}
|
|
84606
84676
|
var Engine = class {
|
|
84607
84677
|
constructor(port2) {
|
|
84608
84678
|
this.port = port2;
|