@metaphi-ai/hum 0.1.9 → 0.1.11
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 +68 -2
- package/package.json +1 -1
- package/scripts/postinstall.js +53 -18
package/dist/cli.mjs
CHANGED
|
@@ -84571,18 +84571,44 @@ function enginePython(dirs = uvToolDirs()) {
|
|
|
84571
84571
|
}
|
|
84572
84572
|
return null;
|
|
84573
84573
|
}
|
|
84574
|
+
function siblingEngine(execPath = process.execPath) {
|
|
84575
|
+
let dir;
|
|
84576
|
+
try {
|
|
84577
|
+
dir = path2.dirname(fs3.realpathSync(execPath));
|
|
84578
|
+
} catch {
|
|
84579
|
+
return null;
|
|
84580
|
+
}
|
|
84581
|
+
const p = path2.join(dir, "engine", win ? "hum-engine.exe" : "hum-engine");
|
|
84582
|
+
return exists(p) ? p : null;
|
|
84583
|
+
}
|
|
84584
|
+
function homeEngine(env3 = process.env) {
|
|
84585
|
+
const home = env3.HUM_HOME || path2.join(os4.homedir(), ".hum");
|
|
84586
|
+
const py = win ? path2.join(home, "engine", "Scripts", "python.exe") : path2.join(home, "engine", "bin", "python");
|
|
84587
|
+
return exists(py) ? py : null;
|
|
84588
|
+
}
|
|
84574
84589
|
function engineCandidates(env3 = process.env) {
|
|
84575
84590
|
const out = [];
|
|
84576
84591
|
if (env3.HUM_ENGINE) {
|
|
84577
84592
|
const [bin, ...args2] = env3.HUM_ENGINE.split(" ");
|
|
84578
84593
|
out.push({ bin, args: args2, where: "HUM_ENGINE" });
|
|
84579
84594
|
}
|
|
84595
|
+
const sib = siblingEngine();
|
|
84596
|
+
if (sib) out.push({ bin: sib, args: ["engine"], where: "beside hum" });
|
|
84597
|
+
const home = homeEngine(env3);
|
|
84598
|
+
if (home) out.push({ bin: home, args: ["-m", "hum.cli", "engine"], where: "HUM_HOME/engine" });
|
|
84580
84599
|
const py = enginePython();
|
|
84581
84600
|
if (py) out.push({ bin: py, args: ["-m", "hum.cli", "engine"], where: "the engine's interpreter" });
|
|
84582
84601
|
out.push({ bin: "hum-engine", args: [], where: "PATH" });
|
|
84583
84602
|
out.push({ bin: path2.join(os4.homedir(), ".local", "bin", win ? "hum-engine.exe" : "hum-engine"), args: [], where: "uv's bin dir" });
|
|
84584
84603
|
return out;
|
|
84585
84604
|
}
|
|
84605
|
+
function engineCommand(argv, candidates = engineCandidates()) {
|
|
84606
|
+
for (const c of candidates) {
|
|
84607
|
+
if (c.args[c.args.length - 1] !== "engine") continue;
|
|
84608
|
+
return { bin: c.bin, args: [...c.args.slice(0, -1), ...argv], where: c.where };
|
|
84609
|
+
}
|
|
84610
|
+
return null;
|
|
84611
|
+
}
|
|
84586
84612
|
function startFailure(failures) {
|
|
84587
84613
|
const refused = failures.find((f) => f.error && f.error.code !== "ENOENT");
|
|
84588
84614
|
if (!refused) {
|
|
@@ -84642,11 +84668,15 @@ function attempt({ bin, args: args2 }, cwd2, { task, images, resume }) {
|
|
|
84642
84668
|
settle(() => resolve(rec));
|
|
84643
84669
|
return;
|
|
84644
84670
|
}
|
|
84671
|
+
if (rec && rec.error) {
|
|
84672
|
+
settle(() => reject({ failed: rec.error }));
|
|
84673
|
+
return;
|
|
84674
|
+
}
|
|
84645
84675
|
if (died && !rec) {
|
|
84646
84676
|
settle(() => reject({ died: logPath }));
|
|
84647
84677
|
return;
|
|
84648
84678
|
}
|
|
84649
|
-
if (Date.now() - t0 >
|
|
84679
|
+
if (Date.now() - t0 > 9e4) {
|
|
84650
84680
|
settle(() => reject({ timeout: true }));
|
|
84651
84681
|
return;
|
|
84652
84682
|
}
|
|
@@ -84655,6 +84685,20 @@ function attempt({ bin, args: args2 }, cwd2, { task, images, resume }) {
|
|
|
84655
84685
|
poll();
|
|
84656
84686
|
});
|
|
84657
84687
|
}
|
|
84688
|
+
function failureMessage(error) {
|
|
84689
|
+
return error.message + (error.hint ? `
|
|
84690
|
+
${error.hint}` : "");
|
|
84691
|
+
}
|
|
84692
|
+
function diedMessage(logPath, text = null) {
|
|
84693
|
+
let tail2 = "";
|
|
84694
|
+
try {
|
|
84695
|
+
tail2 = (text ?? fs3.readFileSync(logPath, "utf8")).trim().split("\n").slice(-3).join("\n").trim();
|
|
84696
|
+
} catch {
|
|
84697
|
+
}
|
|
84698
|
+
return `the engine did not start${tail2 ? `:
|
|
84699
|
+
${tail2}` : ""}
|
|
84700
|
+
(its log: ${logPath})`;
|
|
84701
|
+
}
|
|
84658
84702
|
async function spawnEngine(cwd2, { task = null, images = [], resume = null, candidates = engineCandidates() } = {}) {
|
|
84659
84703
|
const failures = [];
|
|
84660
84704
|
for (const cand of candidates) {
|
|
@@ -84666,7 +84710,8 @@ async function spawnEngine(cwd2, { task = null, images = [], resume = null, cand
|
|
|
84666
84710
|
failures.push({ ...cand, error: f.spawn });
|
|
84667
84711
|
continue;
|
|
84668
84712
|
}
|
|
84669
|
-
if (f && f.
|
|
84713
|
+
if (f && f.failed) throw new EngineError(failureMessage(f.failed));
|
|
84714
|
+
if (f && f.died) throw new EngineError(diedMessage(f.died));
|
|
84670
84715
|
if (f && f.timeout) throw new EngineError("the engine did not start in time");
|
|
84671
84716
|
throw f;
|
|
84672
84717
|
}
|
|
@@ -84746,6 +84791,27 @@ var Engine = class {
|
|
|
84746
84791
|
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
84747
84792
|
import fs4 from "node:fs";
|
|
84748
84793
|
import path3 from "node:path";
|
|
84794
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
84795
|
+
var ENGINE_COMMANDS = /* @__PURE__ */ new Set(["run", "login", "logout", "whoami", "model", "key", "sessions", "show", "sync", "skill", "ps", "stop", "hooks", "engine"]);
|
|
84796
|
+
var argv0 = process.argv.slice(2);
|
|
84797
|
+
if (argv0[0] === "--version" || argv0[0] === "-V") {
|
|
84798
|
+
process.stdout.write(`hum ${true ? "0.1.11" : "0.0.0"}
|
|
84799
|
+
`);
|
|
84800
|
+
process.exit(0);
|
|
84801
|
+
}
|
|
84802
|
+
if (ENGINE_COMMANDS.has(argv0[0])) {
|
|
84803
|
+
const cmd = engineCommand(argv0);
|
|
84804
|
+
if (!cmd) {
|
|
84805
|
+
process.stderr.write(startFailure([]) + "\n");
|
|
84806
|
+
process.exit(1);
|
|
84807
|
+
}
|
|
84808
|
+
const r = spawnSync2(cmd.bin, cmd.args, { stdio: "inherit", windowsHide: true });
|
|
84809
|
+
if (r.error) {
|
|
84810
|
+
process.stderr.write(startFailure([{ bin: cmd.bin, error: r.error }]) + "\n");
|
|
84811
|
+
process.exit(1);
|
|
84812
|
+
}
|
|
84813
|
+
process.exit(r.status === null ? 1 : r.status);
|
|
84814
|
+
}
|
|
84749
84815
|
function parseArgs(argv) {
|
|
84750
84816
|
const a = { task: null, resume: null, cwd: process.cwd(), images: [] };
|
|
84751
84817
|
for (let i = 0; i < argv.length; i += 1) {
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -1,23 +1,58 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
|
|
1
|
+
// The engine, installed beside the person's Hum data: ~/.hum/engine (HUM_HOME/engine), a plain
|
|
2
|
+
// Python environment holding hum-cli at this package's version. No launcher shims are written
|
|
3
|
+
// anywhere — `hum` starts the engine through the environment's own interpreter — so nothing of
|
|
4
|
+
// ours lands in ~/.local/bin, and nothing there can shadow the `hum` npm installed.
|
|
5
|
+
// uv creates the environment (and fetches a Python if the machine has none); it is installed
|
|
6
|
+
// when missing. Quiet when the engine is already at this version; never fails the npm install.
|
|
7
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
8
|
+
import fs from 'node:fs';
|
|
4
9
|
import os from 'node:os';
|
|
5
10
|
import path from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
6
12
|
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
13
|
+
const win = process.platform === 'win32';
|
|
14
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const version = JSON.parse(fs.readFileSync(path.join(here, '..', 'package.json'), 'utf8')).version;
|
|
16
|
+
const home = process.env.HUM_HOME || path.join(os.homedir(), '.hum');
|
|
17
|
+
const env = path.join(home, 'engine');
|
|
18
|
+
const python = win ? path.join(env, 'Scripts', 'python.exe') : path.join(env, 'bin', 'python');
|
|
19
|
+
const localBin = path.join(os.homedir(), '.local', 'bin');
|
|
20
|
+
const say = (m) => console.log(`hum: ${m}`);
|
|
10
21
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
|
|
22
|
+
const run = (cmd, args, opts = {}) => spawnSync(cmd, args, { encoding: 'utf8', windowsHide: true, ...opts });
|
|
23
|
+
const uvNames = ['uv', path.join(localBin, win ? 'uv.exe' : 'uv')];
|
|
24
|
+
const uv = () => uvNames.find((u) => run(u, ['--version']).status === 0);
|
|
25
|
+
|
|
26
|
+
const installed = () => {
|
|
27
|
+
const r = run(python, ['-c', 'import hum; print(hum.__version__)']);
|
|
28
|
+
return r.status === 0 ? r.stdout.trim() : null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
if (installed() === version) process.exit(0);
|
|
33
|
+
let u = uv();
|
|
34
|
+
if (!u) {
|
|
35
|
+
say('installing uv (it creates the engine\'s Python environment) …');
|
|
36
|
+
const r = win
|
|
37
|
+
? run('powershell', ['-ExecutionPolicy', 'ByPass', '-c', 'irm https://astral.sh/uv/install.ps1 | iex'], { stdio: 'inherit' })
|
|
38
|
+
: run('sh', ['-c', 'curl -LsSf https://astral.sh/uv/install.sh | sh'], { stdio: 'inherit' });
|
|
39
|
+
u = r.status === 0 ? uv() : null;
|
|
40
|
+
if (!u) { say('could not install uv; install it from https://astral.sh/uv and run: npm rebuild -g @metaphi-ai/hum'); process.exit(0); }
|
|
41
|
+
}
|
|
42
|
+
say(`installing the engine ${version} into ${env} …`);
|
|
43
|
+
fs.mkdirSync(home, { recursive: true });
|
|
44
|
+
if (run(u, ['venv', '--quiet', '--python', '3.12', env], { stdio: 'inherit' }).status !== 0) throw new Error('uv venv failed');
|
|
45
|
+
if (run(u, ['pip', 'install', '--quiet', '--python', python, `hum-cli==${version}`], { stdio: 'inherit' }).status !== 0) throw new Error('uv pip install failed');
|
|
46
|
+
if (installed() !== version) throw new Error('the engine did not import after install');
|
|
47
|
+
|
|
48
|
+
// An earlier version installed the engine with `uv tool install`, which wrote launcher shims
|
|
49
|
+
// (hum, hum-engine) into ~/.local/bin — where they shadow the `hum` npm installed, and where a
|
|
50
|
+
// managed Windows machine refuses them. That engine is redundant now; take it and its shims out.
|
|
51
|
+
const list = run(u, ['tool', 'list']);
|
|
52
|
+
if (list.status === 0 && /^hum-cli\b/m.test(list.stdout)) {
|
|
53
|
+
if (run(u, ['tool', 'uninstall', 'hum-cli']).status === 0) say(`removed the uv install of hum-cli and its shims in ${localBin}; the engine lives in ${env} now`);
|
|
54
|
+
}
|
|
55
|
+
say(`engine ${version} ready`);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
say(`engine install failed (${e.message}); run: npm rebuild -g @metaphi-ai/hum`);
|
|
23
58
|
}
|