@metaphi-ai/hum 0.1.74 → 0.1.76
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/hum.js +2 -2
- package/dist/cli.mjs +140 -140
- package/dist/install.mjs +18 -18
- package/package.json +1 -1
- package/scripts/postinstall.js +3 -3
package/bin/hum.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// `hum` from npm: the Ink front-end, which starts Hum's
|
|
2
|
+
// `hum` from npm: the Ink front-end, which starts Hum's core (Python, installed by postinstall
|
|
3
3
|
// via uv) and talks to it over localhost. Everything the person sees is here; everything the
|
|
4
|
-
// session records is in the
|
|
4
|
+
// session records is in the core.
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
package/dist/cli.mjs
CHANGED
|
@@ -83195,7 +83195,7 @@ import fs2 from "node:fs";
|
|
|
83195
83195
|
import os3 from "node:os";
|
|
83196
83196
|
import path from "node:path";
|
|
83197
83197
|
function importedVersion(env3 = process.env, runImpl = run) {
|
|
83198
|
-
const r = runImpl(
|
|
83198
|
+
const r = runImpl(corePython(env3), ASK_VERSION);
|
|
83199
83199
|
return r && r.status === 0 ? String(r.stdout).trim() : null;
|
|
83200
83200
|
}
|
|
83201
83201
|
function installedVersion(env3 = process.env, runImpl = run) {
|
|
@@ -83203,7 +83203,7 @@ function installedVersion(env3 = process.env, runImpl = run) {
|
|
|
83203
83203
|
return fs2.readFileSync(stampPath(env3), "utf8").trim() || null;
|
|
83204
83204
|
} catch {
|
|
83205
83205
|
}
|
|
83206
|
-
if (!fs2.existsSync(
|
|
83206
|
+
if (!fs2.existsSync(corePython(env3))) return null;
|
|
83207
83207
|
const v = importedVersion(env3, runImpl);
|
|
83208
83208
|
if (v) {
|
|
83209
83209
|
try {
|
|
@@ -83221,28 +83221,28 @@ function trustedPython(env3 = process.env, runImpl = run) {
|
|
|
83221
83221
|
return /^[a-z]:\\.+\\python(w)?\.exe$/i.test(p) ? p : null;
|
|
83222
83222
|
}
|
|
83223
83223
|
function sslBlocked(env3 = process.env, runImpl = run) {
|
|
83224
|
-
const r = runImpl(
|
|
83224
|
+
const r = runImpl(corePython(env3), ASK_SSL);
|
|
83225
83225
|
if (r && r.status === 0) return null;
|
|
83226
83226
|
const text = String(r && (r.stderr || r.stdout) || "ssl did not import").trim().split(/\r?\n/).filter(Boolean).pop() || "ssl did not import";
|
|
83227
83227
|
return text;
|
|
83228
83228
|
}
|
|
83229
83229
|
function needsInstall(version, { env: env3 = process.env, installed = () => installedVersion(env3), now = Date.now(), state = readInstallState(env3) } = {}) {
|
|
83230
|
-
if (!version || env3.
|
|
83230
|
+
if (!version || env3.HUM_CORE || env3.HUM_CORE_PORT) return false;
|
|
83231
83231
|
if (installed() === version) return false;
|
|
83232
83232
|
if (state && !state.ok && state.version === version && now - (state.at || 0) < 10 * 60 * 1e3) return false;
|
|
83233
83233
|
return true;
|
|
83234
83234
|
}
|
|
83235
|
-
function
|
|
83235
|
+
function installCore(version, { env: env3 = process.env, say = (m) => console.log(`hum: ${m}`), runImpl = run, now = Date.now() } = {}) {
|
|
83236
83236
|
const home = humHome(env3);
|
|
83237
|
-
const dir =
|
|
83238
|
-
const python =
|
|
83237
|
+
const dir = coreDir(env3);
|
|
83238
|
+
const python = corePython(env3);
|
|
83239
83239
|
const localBin = path.join(os3.homedir(), ".local", "bin");
|
|
83240
83240
|
const uvNames = ["uv", path.join(localBin, win ? "uv.exe" : "uv")];
|
|
83241
83241
|
const uv = () => uvNames.find((u) => {
|
|
83242
83242
|
const r = runImpl(u, ["--version"]);
|
|
83243
83243
|
return r && r.status === 0;
|
|
83244
83244
|
});
|
|
83245
|
-
const spec = env3.
|
|
83245
|
+
const spec = env3.HUM_CORE_SPEC || `hum-cli==${version}`;
|
|
83246
83246
|
const outcome = (ok, error = null, got = version) => {
|
|
83247
83247
|
writeInstallState({ version: got, wanted: version, ok, error, at: now }, env3);
|
|
83248
83248
|
return { ok, version: got, error };
|
|
@@ -83255,7 +83255,7 @@ function installEngine(version, { env: env3 = process.env, say = (m) => console.
|
|
|
83255
83255
|
u = r && r.status === 0 ? uv() : null;
|
|
83256
83256
|
if (!u) return outcome(false, `could not install uv; install it from https://astral.sh/uv and run: ${npmFix(version)}`);
|
|
83257
83257
|
}
|
|
83258
|
-
say(`installing ${env3.
|
|
83258
|
+
say(`installing ${env3.HUM_CORE_SPEC ? spec : `hum ${version}`} into ${dir} \u2026`);
|
|
83259
83259
|
fs2.mkdirSync(home, { recursive: true });
|
|
83260
83260
|
try {
|
|
83261
83261
|
fs2.unlinkSync(stampPath(env3));
|
|
@@ -83268,7 +83268,7 @@ function installEngine(version, { env: env3 = process.env, say = (m) => console.
|
|
|
83268
83268
|
if (!pipIn()) return outcome(false, `uv pip install ${spec} failed`);
|
|
83269
83269
|
let got = importedVersion(env3, runImpl);
|
|
83270
83270
|
if (!got) return outcome(false, "hum did not import after the install");
|
|
83271
|
-
if (got !== version && !env3.
|
|
83271
|
+
if (got !== version && !env3.HUM_CORE_SPEC) return outcome(false, `installed ${got}, wanted ${version}`, got);
|
|
83272
83272
|
let blocked = sslBlocked(env3, runImpl);
|
|
83273
83273
|
if (blocked && trusted) {
|
|
83274
83274
|
say(`the policy here refuses the environment's OpenSSL (${blocked}); rebuilding it on ${trusted} \u2026`);
|
|
@@ -83292,21 +83292,21 @@ function installEngine(version, { env: env3 = process.env, say = (m) => console.
|
|
|
83292
83292
|
return outcome(false, e && e.message ? e.message : String(e));
|
|
83293
83293
|
}
|
|
83294
83294
|
}
|
|
83295
|
-
var win, npmFix, NPM_FIX, humHome,
|
|
83295
|
+
var win, npmFix, NPM_FIX, humHome, coreDir, corePython, stampPath, statePath, run, ASK_VERSION, ASK_SSL, sslAdvice, readInstallState, writeInstallState;
|
|
83296
83296
|
var init_install = __esm({
|
|
83297
83297
|
"src/install.js"() {
|
|
83298
83298
|
win = process.platform === "win32";
|
|
83299
83299
|
npmFix = (version = "") => `npm i -g @metaphi-ai/hum@${version || "latest"} --foreground-scripts`;
|
|
83300
83300
|
NPM_FIX = npmFix("latest");
|
|
83301
83301
|
humHome = (env3 = process.env) => env3.HUM_HOME || path.join(os3.homedir(), ".hum");
|
|
83302
|
-
|
|
83303
|
-
|
|
83304
|
-
stampPath = (env3) => path.join(
|
|
83305
|
-
statePath = (env3) => path.join(humHome(env3), "
|
|
83302
|
+
coreDir = (env3 = process.env) => path.join(humHome(env3), "core");
|
|
83303
|
+
corePython = (env3 = process.env) => win ? path.join(coreDir(env3), "Scripts", "python.exe") : path.join(coreDir(env3), "bin", "python");
|
|
83304
|
+
stampPath = (env3) => path.join(coreDir(env3), "version");
|
|
83305
|
+
statePath = (env3) => path.join(humHome(env3), "core-install.json");
|
|
83306
83306
|
run = (cmd, args2, opts = {}) => spawnSync(cmd, args2, { encoding: "utf8", windowsHide: true, ...opts });
|
|
83307
83307
|
ASK_VERSION = ["-I", "-c", "import hum; print(hum.__version__)"];
|
|
83308
83308
|
ASK_SSL = ["-I", "-c", "import ssl"];
|
|
83309
|
-
sslAdvice = (env3, version) => `the machine's application control blocked Python's OpenSSL DLL in ${
|
|
83309
|
+
sslAdvice = (env3, version) => `the machine's application control blocked Python's OpenSSL DLL in ${coreDir(env3)}; install Python 3.12 from python.org (Microsoft signs it), then run ${npmFix(version)}`;
|
|
83310
83310
|
readInstallState = (env3 = process.env) => {
|
|
83311
83311
|
try {
|
|
83312
83312
|
return JSON.parse(fs2.readFileSync(statePath(env3), "utf8"));
|
|
@@ -83342,7 +83342,7 @@ async function latestVersion(fetchImpl = globalThis.fetch, env3 = process.env) {
|
|
|
83342
83342
|
}
|
|
83343
83343
|
function installLayout(execPath = process.execPath, env3 = process.env) {
|
|
83344
83344
|
const exe = String(execPath).split(/[\\/]/).pop();
|
|
83345
|
-
if (/^(node|bun)(\.exe)?$/i.test(exe)) return { kind: env3.
|
|
83345
|
+
if (/^(node|bun)(\.exe)?$/i.test(exe)) return { kind: env3.HUM_CORE_PORT ? "python" : "npm" };
|
|
83346
83346
|
let real = execPath;
|
|
83347
83347
|
try {
|
|
83348
83348
|
real = fs3.realpathSync(execPath);
|
|
@@ -83395,7 +83395,7 @@ function startBackgroundUpdate(version, { env: env3 = process.env, now = Date.no
|
|
|
83395
83395
|
function mismatchLine(mine, running, { env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3), state = readInstallState(env3) } = {}) {
|
|
83396
83396
|
if (!mine || !running || mine === running) return "";
|
|
83397
83397
|
const head = `hum ${mine} is installed but ${running} is what runs`;
|
|
83398
|
-
if (env3.
|
|
83398
|
+
if (env3.HUM_CORE) return `${head}: HUM_CORE points at it \xB7 unset HUM_CORE to use ${mine}`;
|
|
83399
83399
|
const fix = layout2.kind === "npm" ? npmFix(mine) : updateCommand(layout2);
|
|
83400
83400
|
if (state && !state.ok && state.wanted === mine && state.error) return `${head}: the update did not finish (${state.error}) \xB7 ${fix}`;
|
|
83401
83401
|
return `${head} \xB7 ${fix}`;
|
|
@@ -83484,7 +83484,7 @@ var init_update = __esm({
|
|
|
83484
83484
|
}
|
|
83485
83485
|
});
|
|
83486
83486
|
|
|
83487
|
-
// src/
|
|
83487
|
+
// src/core.js
|
|
83488
83488
|
import fs4 from "node:fs";
|
|
83489
83489
|
import net from "node:net";
|
|
83490
83490
|
import os5 from "node:os";
|
|
@@ -83511,57 +83511,57 @@ function uvToolDirs() {
|
|
|
83511
83511
|
}
|
|
83512
83512
|
return dirs;
|
|
83513
83513
|
}
|
|
83514
|
-
function
|
|
83514
|
+
function corePython2(dirs = uvToolDirs()) {
|
|
83515
83515
|
for (const dir of dirs) for (const name of ["hum-cli", "hum"]) {
|
|
83516
83516
|
const py = win3 ? path3.join(dir, name, "Scripts", "python.exe") : path3.join(dir, name, "bin", "python");
|
|
83517
83517
|
if (exists(py)) return py;
|
|
83518
83518
|
}
|
|
83519
83519
|
return null;
|
|
83520
83520
|
}
|
|
83521
|
-
function
|
|
83521
|
+
function siblingCore(execPath = process.execPath) {
|
|
83522
83522
|
let dir;
|
|
83523
83523
|
try {
|
|
83524
83524
|
dir = path3.dirname(fs4.realpathSync(execPath));
|
|
83525
83525
|
} catch {
|
|
83526
83526
|
return null;
|
|
83527
83527
|
}
|
|
83528
|
-
const p = path3.join(dir, "
|
|
83528
|
+
const p = path3.join(dir, "core", win3 ? "hum-core.exe" : "hum-core");
|
|
83529
83529
|
return exists(p) ? p : null;
|
|
83530
83530
|
}
|
|
83531
|
-
function
|
|
83531
|
+
function homeCore(env3 = process.env) {
|
|
83532
83532
|
const home = env3.HUM_HOME || path3.join(os5.homedir(), ".hum");
|
|
83533
|
-
const py = win3 ? path3.join(home, "
|
|
83533
|
+
const py = win3 ? path3.join(home, "core", "Scripts", "python.exe") : path3.join(home, "core", "bin", "python");
|
|
83534
83534
|
return exists(py) ? py : null;
|
|
83535
83535
|
}
|
|
83536
|
-
function
|
|
83536
|
+
function coreCandidates(env3 = process.env) {
|
|
83537
83537
|
const out = [];
|
|
83538
|
-
if (env3.
|
|
83539
|
-
const [bin, ...args2] = env3.
|
|
83540
|
-
out.push({ bin, args: args2, where: "
|
|
83541
|
-
}
|
|
83542
|
-
const sib =
|
|
83543
|
-
if (sib) out.push({ bin: sib, args: ["
|
|
83544
|
-
const home =
|
|
83545
|
-
if (home) out.push({ bin: home, args: ["-m", "hum.cli", "
|
|
83546
|
-
const py =
|
|
83547
|
-
if (py) out.push({ bin: py, args: ["-m", "hum.cli", "
|
|
83548
|
-
out.push({ bin: "hum-
|
|
83549
|
-
out.push({ bin: path3.join(os5.homedir(), ".local", "bin", win3 ? "hum-
|
|
83538
|
+
if (env3.HUM_CORE) {
|
|
83539
|
+
const [bin, ...args2] = env3.HUM_CORE.split(" ");
|
|
83540
|
+
out.push({ bin, args: args2, where: "HUM_CORE" });
|
|
83541
|
+
}
|
|
83542
|
+
const sib = siblingCore();
|
|
83543
|
+
if (sib) out.push({ bin: sib, args: ["core"], where: "beside hum" });
|
|
83544
|
+
const home = homeCore(env3);
|
|
83545
|
+
if (home) out.push({ bin: home, args: ["-m", "hum.cli", "core"], where: "HUM_HOME/core" });
|
|
83546
|
+
const py = corePython2();
|
|
83547
|
+
if (py) out.push({ bin: py, args: ["-m", "hum.cli", "core"], where: "the interpreter beside it" });
|
|
83548
|
+
out.push({ bin: "hum-core", args: [], where: "PATH" });
|
|
83549
|
+
out.push({ bin: path3.join(os5.homedir(), ".local", "bin", win3 ? "hum-core.exe" : "hum-core"), args: [], where: "uv's bin dir" });
|
|
83550
83550
|
return out;
|
|
83551
83551
|
}
|
|
83552
83552
|
function wantsPlain(argv, env3 = process.env) {
|
|
83553
83553
|
return argv.includes("--plain") || !!env3.HUM_PLAIN;
|
|
83554
83554
|
}
|
|
83555
|
-
function
|
|
83555
|
+
function coreCommand(argv, candidates = coreCandidates()) {
|
|
83556
83556
|
for (const c of candidates) {
|
|
83557
|
-
if (c.args[c.args.length - 1] !== "
|
|
83557
|
+
if (c.args[c.args.length - 1] !== "core") continue;
|
|
83558
83558
|
return { bin: c.bin, args: [...c.args.slice(0, -1), ...argv], where: c.where };
|
|
83559
83559
|
}
|
|
83560
83560
|
return null;
|
|
83561
83561
|
}
|
|
83562
83562
|
function candidateVersion(c, { env: env3 = process.env, runImpl = spawnSync3 } = {}) {
|
|
83563
83563
|
if (!c || !c.bin) return null;
|
|
83564
|
-
if (c.where === "HUM_HOME/
|
|
83564
|
+
if (c.where === "HUM_HOME/core") return installedVersion(env3);
|
|
83565
83565
|
const interp = c.args.length >= 3 && c.args[c.args.length - 3] === "-m" && c.args[c.args.length - 2] === "hum.cli";
|
|
83566
83566
|
let r;
|
|
83567
83567
|
try {
|
|
@@ -83573,18 +83573,18 @@ function candidateVersion(c, { env: env3 = process.env, runImpl = spawnSync3 } =
|
|
|
83573
83573
|
const m = String(r.stdout || "").match(/(\d+\.\d+\.\d+)/);
|
|
83574
83574
|
return m ? m[1] : null;
|
|
83575
83575
|
}
|
|
83576
|
-
function runningVersion(candidates =
|
|
83576
|
+
function runningVersion(candidates = coreCandidates(), opts = {}) {
|
|
83577
83577
|
for (const c of candidates) {
|
|
83578
83578
|
const v = candidateVersion(c, opts);
|
|
83579
83579
|
if (v) return { version: v, where: c.where };
|
|
83580
83580
|
}
|
|
83581
83581
|
return null;
|
|
83582
83582
|
}
|
|
83583
|
-
function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.1.
|
|
83583
|
+
function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.1.76" : "" } = {}) {
|
|
83584
83584
|
const refused = failures.find((f) => f.error && f.error.code !== "ENOENT");
|
|
83585
83585
|
const fix = npm ? npmFix(version) : updateCommand({ kind: "native" }, platform2);
|
|
83586
83586
|
if (!refused) {
|
|
83587
|
-
return `Hum is not fully installed here \u2014 the half that does the work is missing. Run: ${fix} (or set
|
|
83587
|
+
return `Hum is not fully installed here \u2014 the half that does the work is missing. Run: ${fix} (or set HUM_CORE to the command that runs it)`;
|
|
83588
83588
|
}
|
|
83589
83589
|
const what = refused.error.code || refused.error.message;
|
|
83590
83590
|
const lines = [
|
|
@@ -83594,9 +83594,9 @@ function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(proc
|
|
|
83594
83594
|
lines.push("On a managed Windows machine that is usually Device Guard / WDAC refusing an executable it does not know.");
|
|
83595
83595
|
lines.push(`To see the policy's own message, run: "${refused.bin}" --help`);
|
|
83596
83596
|
const dir = uvToolDirs()[0];
|
|
83597
|
-
lines.push(`If uv's environment is elsewhere, point Hum at its interpreter: set
|
|
83597
|
+
lines.push(`If uv's environment is elsewhere, point Hum at its interpreter: set HUM_CORE=${path3.join(dir || "<uv tool dir>", "hum-cli", "Scripts", "python.exe")} -m hum.cli core`);
|
|
83598
83598
|
} else {
|
|
83599
|
-
lines.push('Set
|
|
83599
|
+
lines.push('Set HUM_CORE to a command that starts it, e.g. HUM_CORE="python -m hum.cli core"');
|
|
83600
83600
|
}
|
|
83601
83601
|
return lines.join("\n");
|
|
83602
83602
|
}
|
|
@@ -83671,7 +83671,7 @@ function diedMessage(logPath, text = null) {
|
|
|
83671
83671
|
${tail2}` : ""}
|
|
83672
83672
|
(its log: ${logPath})`;
|
|
83673
83673
|
}
|
|
83674
|
-
async function
|
|
83674
|
+
async function spawnCore(cwd2, { task = null, images = [], resume = null, candidates = coreCandidates() } = {}) {
|
|
83675
83675
|
const failures = [];
|
|
83676
83676
|
for (const cand of candidates) {
|
|
83677
83677
|
if (!cand.bin) continue;
|
|
@@ -83690,9 +83690,9 @@ async function spawnEngine(cwd2, { task = null, images = [], resume = null, cand
|
|
|
83690
83690
|
}
|
|
83691
83691
|
throw new EngineError(startFailure(failures));
|
|
83692
83692
|
}
|
|
83693
|
-
var runDir, readRun, EngineError, win3, exists,
|
|
83694
|
-
var
|
|
83695
|
-
"src/
|
|
83693
|
+
var runDir, readRun, EngineError, win3, exists, Core;
|
|
83694
|
+
var init_core = __esm({
|
|
83695
|
+
"src/core.js"() {
|
|
83696
83696
|
init_install();
|
|
83697
83697
|
init_update();
|
|
83698
83698
|
runDir = () => path3.join(process.env.HUM_HOME || path3.join(os5.homedir(), ".hum"), "run");
|
|
@@ -83714,16 +83714,16 @@ var init_engine = __esm({
|
|
|
83714
83714
|
return false;
|
|
83715
83715
|
}
|
|
83716
83716
|
};
|
|
83717
|
-
|
|
83717
|
+
Core = class {
|
|
83718
83718
|
constructor(port2, token2 = "") {
|
|
83719
83719
|
this.port = port2;
|
|
83720
83720
|
this.token = token2;
|
|
83721
83721
|
this.handlers = [];
|
|
83722
83722
|
this.closed = false;
|
|
83723
83723
|
}
|
|
83724
|
-
// This front-end has a person at it: it says so on connecting, and the
|
|
83724
|
+
// This front-end has a person at it: it says so on connecting, and the core counts it as
|
|
83725
83725
|
// one. Only a human front-end makes the session attended. The same line carries the run's
|
|
83726
|
-
// token, which the
|
|
83726
|
+
// token, which the core reads before it says anything back.
|
|
83727
83727
|
connect() {
|
|
83728
83728
|
return new Promise((resolve, reject) => {
|
|
83729
83729
|
const sock = net.createConnection({ host: "127.0.0.1", port: this.port }, () => {
|
|
@@ -83761,7 +83761,7 @@ var init_engine = __esm({
|
|
|
83761
83761
|
});
|
|
83762
83762
|
});
|
|
83763
83763
|
}
|
|
83764
|
-
// Attach to another
|
|
83764
|
+
// Attach to another core (a session running elsewhere on this machine): its token comes
|
|
83765
83765
|
// from its run file, the old socket is dropped quietly, the new one greets us with hello
|
|
83766
83766
|
// and a replay.
|
|
83767
83767
|
async reconnect(port2, token2 = "") {
|
|
@@ -83936,9 +83936,9 @@ function replayLines(items, n = 20) {
|
|
|
83936
83936
|
}
|
|
83937
83937
|
return out.slice(-n);
|
|
83938
83938
|
}
|
|
83939
|
-
async function peekSession(row, ready, make = (port2, token2) => new
|
|
83939
|
+
async function peekSession(row, ready, make = (port2, token2) => new Core(port2, token2)) {
|
|
83940
83940
|
const token2 = (readRun(row.run_id) || {}).token || "";
|
|
83941
|
-
const
|
|
83941
|
+
const core2 = make(row.port, token2);
|
|
83942
83942
|
let timer = null;
|
|
83943
83943
|
let done = false;
|
|
83944
83944
|
let replay = [];
|
|
@@ -83948,26 +83948,26 @@ async function peekSession(row, ready, make = (port2, token2) => new Engine(port
|
|
|
83948
83948
|
clearTimeout(timer);
|
|
83949
83949
|
ready({ question, lines: replayLines(replay) });
|
|
83950
83950
|
};
|
|
83951
|
-
|
|
83951
|
+
core2.on((ev) => {
|
|
83952
83952
|
if (ev.type === "replay") {
|
|
83953
83953
|
replay = ev.items || [];
|
|
83954
83954
|
timer = setTimeout(() => settle(null), PEEK_SETTLE_MS);
|
|
83955
83955
|
} else if (ev.type === "question") settle(asked(ev));
|
|
83956
83956
|
else if (ev.type === "bye") settle(null);
|
|
83957
83957
|
});
|
|
83958
|
-
await
|
|
83958
|
+
await core2.connect();
|
|
83959
83959
|
return {
|
|
83960
|
-
answer: (id, text) =>
|
|
83960
|
+
answer: (id, text) => core2.send({ cmd: "answer", id, text }),
|
|
83961
83961
|
close: () => {
|
|
83962
83962
|
clearTimeout(timer);
|
|
83963
|
-
|
|
83963
|
+
core2.close();
|
|
83964
83964
|
}
|
|
83965
83965
|
};
|
|
83966
83966
|
}
|
|
83967
83967
|
var firstLine, rank, needCount, stateText, fmtCost, PEEK_SETTLE_MS, asked;
|
|
83968
83968
|
var init_agents = __esm({
|
|
83969
83969
|
"src/agents.js"() {
|
|
83970
|
-
|
|
83970
|
+
init_core();
|
|
83971
83971
|
firstLine = (s) => (s || "").trim().split("\n")[0] || "";
|
|
83972
83972
|
rank = (r) => r.needs ? 0 : r.state === "busy" ? 1 : 2;
|
|
83973
83973
|
needCount = (rows, mine) => rows.filter((r) => r.needs && r.run_id !== mine).length;
|
|
@@ -84934,7 +84934,7 @@ function jsonError(text, e) {
|
|
|
84934
84934
|
return `line ${line}: ${msg.replace(/ in JSON.*$/, "")}`;
|
|
84935
84935
|
}
|
|
84936
84936
|
function onPath(env3, { platform: platform2 = process.platform } = {}) {
|
|
84937
|
-
const names = isWin(platform2) ? ["hum.cmd", "hum.exe", "hum", "hum-
|
|
84937
|
+
const names = isWin(platform2) ? ["hum.cmd", "hum.exe", "hum", "hum-core.exe", "hum-core.cmd"] : ["hum", "hum-core"];
|
|
84938
84938
|
const seen = /* @__PURE__ */ new Set();
|
|
84939
84939
|
const hits = [];
|
|
84940
84940
|
for (const dir of String(env3.PATH || env3.Path || "").split(path6.delimiter).filter(Boolean)) {
|
|
@@ -84955,7 +84955,7 @@ async function diagnose({
|
|
|
84955
84955
|
homedir = os7.homedir(),
|
|
84956
84956
|
cwd: cwd2 = process.cwd(),
|
|
84957
84957
|
layout: layout2 = installLayout(execPath, env3),
|
|
84958
|
-
candidates =
|
|
84958
|
+
candidates = coreCandidates(env3),
|
|
84959
84959
|
runImpl = spawnSync4,
|
|
84960
84960
|
fetchImpl = globalThis.fetch
|
|
84961
84961
|
} = {}) {
|
|
@@ -84976,8 +84976,8 @@ async function diagnose({
|
|
|
84976
84976
|
}
|
|
84977
84977
|
}
|
|
84978
84978
|
const hits = onPath(env3, { platform: platform2 });
|
|
84979
|
-
const hums = hits.filter((h) => !h.name.startsWith("hum-
|
|
84980
|
-
const stale = hits.filter((h) => h.name.startsWith("hum-
|
|
84979
|
+
const hums = hits.filter((h) => !h.name.startsWith("hum-core"));
|
|
84980
|
+
const stale = hits.filter((h) => h.name.startsWith("hum-core"));
|
|
84981
84981
|
const targets = new Set(hums.map((h) => h.real));
|
|
84982
84982
|
if (hums.length === 0) checks.push(check("warn", "no hum on PATH: a new terminal may not find it", layout2.kind === "native" ? isWin(platform2) ? "open a new terminal" : 'export PATH="$HOME/.local/bin:$PATH"' : "npm bin -g, and put that directory on PATH"));
|
|
84983
84983
|
else if (targets.size > 1) checks.push(check("warn", `more than one hum on PATH; the first wins: ${hums.map((h) => h.path).join(" \xB7 ")}`, "remove the ones you did not mean to keep"));
|
|
@@ -84988,7 +84988,7 @@ async function diagnose({
|
|
|
84988
84988
|
let running = null;
|
|
84989
84989
|
{
|
|
84990
84990
|
const checks = [];
|
|
84991
|
-
if (env3.
|
|
84991
|
+
if (env3.HUM_CORE_PORT) checks.push(check("ok", `started by Python for this hum (HUM_CORE_PORT=${env3.HUM_CORE_PORT})`));
|
|
84992
84992
|
for (const c of candidates) {
|
|
84993
84993
|
const v = candidateVersion(c, { env: env3, runImpl });
|
|
84994
84994
|
if (v) {
|
|
@@ -84998,7 +84998,7 @@ async function diagnose({
|
|
|
84998
84998
|
}
|
|
84999
84999
|
if (!running) checks.push(check("fail", "nothing answers: the part of hum that does the work is missing", layout2.kind === "npm" ? npmFix2(mine) : updateCommand(layout2, platform2)));
|
|
85000
85000
|
else if (running.version === mine) checks.push(check("ok", `${running.version} runs from ${running.where} (${running.bin})`));
|
|
85001
|
-
else if (env3.
|
|
85001
|
+
else if (env3.HUM_CORE) checks.push(check("fail", `${running.version} is what runs: HUM_CORE points at it (${env3.HUM_CORE}); you installed ${mine}`, "unset HUM_CORE"));
|
|
85002
85002
|
else checks.push(check("fail", `${running.version} is what runs (${running.where}: ${running.bin}); you installed ${mine}`, layout2.kind === "npm" ? npmFix2(mine) : updateCommand(layout2, platform2)));
|
|
85003
85003
|
if (running && running.args.includes("-m")) {
|
|
85004
85004
|
const r = runImpl(running.bin, ["-I", "-c", "import ssl"], { encoding: "utf8", windowsHide: true, timeout: 2e4 });
|
|
@@ -85012,16 +85012,16 @@ async function diagnose({
|
|
|
85012
85012
|
));
|
|
85013
85013
|
}
|
|
85014
85014
|
}
|
|
85015
|
-
if (env3.
|
|
85015
|
+
if (env3.HUM_CORE && running && running.version === mine) checks.push(check("warn", `HUM_CORE is set (${env3.HUM_CORE}): it decides what runs, ahead of any install`, "unset HUM_CORE"));
|
|
85016
85016
|
if (layout2.kind === "npm") {
|
|
85017
85017
|
const st = readInstallState(env3);
|
|
85018
85018
|
const stamp = installedVersion(env3, runImpl);
|
|
85019
85019
|
if (st && !st.ok) checks.push(check(stamp === mine ? "warn" : "fail", `the last install attempt (wanted ${st.wanted || st.version}) did not finish: ${st.error}`, npmFix2(mine)));
|
|
85020
|
-
else if (!stamp) checks.push(check("fail", `nothing installed under ${
|
|
85021
|
-
else checks.push(check(stamp === mine ? "ok" : "warn", `${
|
|
85020
|
+
else if (!stamp) checks.push(check("fail", `nothing installed under ${coreDir(env3)}`, npmFix2(mine)));
|
|
85021
|
+
else checks.push(check(stamp === mine ? "ok" : "warn", `${coreDir(env3)} holds ${stamp}`, stamp === mine ? "" : npmFix2(mine)));
|
|
85022
85022
|
}
|
|
85023
85023
|
if (layout2.kind === "native") {
|
|
85024
|
-
const sib = path6.join(layout2.dir, "
|
|
85024
|
+
const sib = path6.join(layout2.dir, "core", isWin(platform2) ? "hum-core.exe" : "hum-core");
|
|
85025
85025
|
checks.push(exists2(sib) ? check("ok", `the working half is beside hum: ${sib}`) : check("fail", `nothing beside hum at ${sib}: the install is incomplete`, updateCommand(layout2, platform2)));
|
|
85026
85026
|
}
|
|
85027
85027
|
sections.push({ key: "runtime", title: "The part of hum that does the work", checks });
|
|
@@ -85043,7 +85043,7 @@ async function diagnose({
|
|
|
85043
85043
|
else if (latest) checks.push(check("ok", `${mine} is the latest release`));
|
|
85044
85044
|
sections.push({ key: "updates", title: "Updates", checks });
|
|
85045
85045
|
}
|
|
85046
|
-
const interp = running && running.args.length >= 3 && running.args[running.args.length - 2] === "hum.cli" ? running.bin : exists2(
|
|
85046
|
+
const interp = running && running.args.length >= 3 && running.args[running.args.length - 2] === "hum.cli" ? running.bin : exists2(corePython(env3)) ? corePython(env3) : null;
|
|
85047
85047
|
let toolServers = null;
|
|
85048
85048
|
{
|
|
85049
85049
|
const checks = [];
|
|
@@ -85070,7 +85070,7 @@ async function diagnose({
|
|
|
85070
85070
|
toolServers = parsed.mcp;
|
|
85071
85071
|
}
|
|
85072
85072
|
}
|
|
85073
|
-
for (const f of [path6.join(home, "hooks.json"), path6.join(cwd2, ".hum", "hooks.json"), path6.join(home, "autonomy.json"), path6.join(home, "update.json"), path6.join(home, "
|
|
85073
|
+
for (const f of [path6.join(home, "hooks.json"), path6.join(cwd2, ".hum", "hooks.json"), path6.join(home, "autonomy.json"), path6.join(home, "update.json"), path6.join(home, "core-install.json")]) {
|
|
85074
85074
|
if (!exists2(f)) continue;
|
|
85075
85075
|
const text = fs7.readFileSync(f, "utf8");
|
|
85076
85076
|
try {
|
|
@@ -85148,7 +85148,7 @@ async function doctor({ json = false, mine, write = (t) => process.stdout.write(
|
|
|
85148
85148
|
var isWin, npmFix2, exists2, realpath, tail, check, PARSE_CONFIG, MARK;
|
|
85149
85149
|
var init_doctor = __esm({
|
|
85150
85150
|
"src/doctor.js"() {
|
|
85151
|
-
|
|
85151
|
+
init_core();
|
|
85152
85152
|
init_install();
|
|
85153
85153
|
init_update();
|
|
85154
85154
|
isWin = (platform2) => platform2 === "win32";
|
|
@@ -85453,7 +85453,7 @@ function bannerLines(ev, homeRel2 = (p) => p, mine = "") {
|
|
|
85453
85453
|
|
|
85454
85454
|
// src/app.jsx
|
|
85455
85455
|
init_update();
|
|
85456
|
-
|
|
85456
|
+
init_core();
|
|
85457
85457
|
init_agents();
|
|
85458
85458
|
|
|
85459
85459
|
// src/input.jsx
|
|
@@ -85599,7 +85599,7 @@ var input_default = MultilineInput;
|
|
|
85599
85599
|
|
|
85600
85600
|
// src/app.jsx
|
|
85601
85601
|
var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
|
|
85602
|
-
var MINE = true ? "0.1.
|
|
85602
|
+
var MINE = true ? "0.1.76" : "";
|
|
85603
85603
|
var fmtDur = (s) => s < 60 ? `${Math.max(1, Math.round(s))}s` : `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;
|
|
85604
85604
|
var plural = (n, w) => `${n} ${w}${n === 1 ? "" : "s"}`;
|
|
85605
85605
|
var firstResp = (e) => e.first_response_s ? ` \xB7 first response ${e.first_response_s.toFixed(1)}s` : "";
|
|
@@ -85686,7 +85686,7 @@ var COMMANDS = [
|
|
|
85686
85686
|
{ name: "/goal", desc: "the goal the session keeps working toward on its own, exchange after exchange, until the model marks it complete or blocked (/goal <objective>; /goal pause \xB7 resume \xB7 clear; /goal alone shows where it stands)" },
|
|
85687
85687
|
{ name: "/image", desc: "attach an image file to your next message (/image <path>); ctrl+v pastes a screenshot" },
|
|
85688
85688
|
{ name: "/mcp", desc: "the MCP servers in this session \u2014 what each mounted, and any that did not" },
|
|
85689
|
-
{ name: "/
|
|
85689
|
+
{ name: "/slack", desc: "this session's Slack thread \u2014 opened now in the declared channel when it has none \u2014 and whether you are paired" },
|
|
85690
85690
|
{ name: "/tools", desc: "the tools the model has, and the sandbox they run in" },
|
|
85691
85691
|
{ name: "/hooks", desc: "the lifecycle hooks in scope (~/.hum/hooks.json, <repo>/.hum/hooks.json; Claude Code and Codex hook files too)" },
|
|
85692
85692
|
{ name: "/permissions", desc: "the rules in force here \u2014 what runs without asking, what is refused, and where each rule came from" },
|
|
@@ -85723,7 +85723,7 @@ var tallyLine = (tally) => Object.entries(tally).map(([name, t]) => {
|
|
|
85723
85723
|
const parts = [t.ok ? `${t.ok} ok` : null, t.failed ? `${t.failed} failed` : null, t.error ? `${t.error} error` : null].filter(Boolean);
|
|
85724
85724
|
return `${short} ${parts.join(" \xB7 ")}`;
|
|
85725
85725
|
}).join(" ");
|
|
85726
|
-
function App2({
|
|
85726
|
+
function App2({ core: core2, task, resume, images = [], peek = peekSession, update = updateNotice, watch = watchReady }) {
|
|
85727
85727
|
const { exit } = use_app_default();
|
|
85728
85728
|
const { stdout } = use_stdout_default();
|
|
85729
85729
|
const width = (stdout?.columns || 80) - 2;
|
|
@@ -85981,17 +85981,17 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
85981
85981
|
if (startedRef.current) break;
|
|
85982
85982
|
startedRef.current = true;
|
|
85983
85983
|
if (ev.session) {
|
|
85984
|
-
if (resume === "pick")
|
|
85984
|
+
if (resume === "pick") core2.send({ cmd: "sessions" });
|
|
85985
85985
|
} else if (task) {
|
|
85986
85986
|
if (images.length && !ev.images) append({ kind: "warn", text: "this version of hum does not take images; update hum" });
|
|
85987
|
-
|
|
85987
|
+
core2.send({ cmd: "start", task, images: ev.images ? images : [] });
|
|
85988
85988
|
} else if (resume === "pick") {
|
|
85989
85989
|
setPhaseBoth("idle");
|
|
85990
|
-
|
|
85991
|
-
} else if (resume)
|
|
85990
|
+
core2.send({ cmd: "sessions" });
|
|
85991
|
+
} else if (resume) core2.send({ cmd: "resume", name: resume });
|
|
85992
85992
|
else {
|
|
85993
85993
|
setPhaseBoth("idle");
|
|
85994
|
-
if (ev.images) images.forEach((p) =>
|
|
85994
|
+
if (ev.images) images.forEach((p) => core2.send({ cmd: "attach", path: p }));
|
|
85995
85995
|
else if (images.length) append({ kind: "warn", text: "this version of hum does not take images; update hum" });
|
|
85996
85996
|
}
|
|
85997
85997
|
break;
|
|
@@ -86314,7 +86314,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86314
86314
|
}
|
|
86315
86315
|
};
|
|
86316
86316
|
(0, import_react24.useEffect)(() => {
|
|
86317
|
-
|
|
86317
|
+
core2.on(handle);
|
|
86318
86318
|
}, []);
|
|
86319
86319
|
(0, import_react24.useEffect)(() => {
|
|
86320
86320
|
const mine = hello && hello.run_id;
|
|
@@ -86342,14 +86342,14 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86342
86342
|
if (phaseRef.current === "dead") return;
|
|
86343
86343
|
const busy = phaseRef.current === "busy";
|
|
86344
86344
|
append({ kind: "info", text: !session ? "bye" : busy ? "still working \xB7 `hum resume` brings you back" : `saved \xB7 \`hum resume\` brings you back` });
|
|
86345
|
-
|
|
86345
|
+
core2.send({ cmd: "quit" });
|
|
86346
86346
|
setPhaseBoth("dead");
|
|
86347
86347
|
setTimeout(() => exit(), 400);
|
|
86348
86348
|
};
|
|
86349
86349
|
const stop = () => {
|
|
86350
86350
|
if (phaseRef.current === "dead") return;
|
|
86351
86351
|
append({ kind: "info", text: session ? `stopped \xB7 saved \xB7 hum resume ${shortSession(session)}` : "stopped" });
|
|
86352
|
-
|
|
86352
|
+
core2.send({ cmd: "stop" });
|
|
86353
86353
|
setTimeout(() => {
|
|
86354
86354
|
setPhaseBoth("dead");
|
|
86355
86355
|
exit();
|
|
@@ -86363,7 +86363,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86363
86363
|
}
|
|
86364
86364
|
setCtrlc(1);
|
|
86365
86365
|
setTimeout(() => setCtrlc(0), 1500);
|
|
86366
|
-
if (phaseRef.current === "busy")
|
|
86366
|
+
if (phaseRef.current === "busy") core2.send({ cmd: "interrupt" });
|
|
86367
86367
|
return;
|
|
86368
86368
|
}
|
|
86369
86369
|
if (key.ctrl && input === "d") {
|
|
@@ -86412,7 +86412,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86412
86412
|
if (confirm && !picker) {
|
|
86413
86413
|
if (key.return) {
|
|
86414
86414
|
setConfirm(null);
|
|
86415
|
-
|
|
86415
|
+
core2.send({ cmd: "rewind", to: confirm.node, ...rewindRef.current, confirm: true });
|
|
86416
86416
|
return;
|
|
86417
86417
|
}
|
|
86418
86418
|
if (key.escape) {
|
|
@@ -86441,7 +86441,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86441
86441
|
setPicker(null);
|
|
86442
86442
|
if (!it) return;
|
|
86443
86443
|
rewindRef.current = { files: c !== "chat", conversation: c !== "files" };
|
|
86444
|
-
|
|
86444
|
+
core2.send({ cmd: "rewind", to: it.node, ...rewindRef.current });
|
|
86445
86445
|
};
|
|
86446
86446
|
if (key.upArrow) setPicker((pk) => ({ ...pk, choice: (pk.choice + REWIND_CHOICES.length - 1) % REWIND_CHOICES.length }));
|
|
86447
86447
|
else if (key.downArrow || key.tab) setPicker((pk) => ({ ...pk, choice: (pk.choice + 1) % REWIND_CHOICES.length }));
|
|
@@ -86478,7 +86478,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86478
86478
|
}
|
|
86479
86479
|
if (key.escape) {
|
|
86480
86480
|
setProposal(null);
|
|
86481
|
-
|
|
86481
|
+
core2.send({ cmd: "interrupt" });
|
|
86482
86482
|
return;
|
|
86483
86483
|
}
|
|
86484
86484
|
}
|
|
@@ -86527,7 +86527,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86527
86527
|
const pick = (keep) => {
|
|
86528
86528
|
setPicker(null);
|
|
86529
86529
|
if (it.current && !(keep && !it.default)) return;
|
|
86530
|
-
|
|
86530
|
+
core2.send(keep ? { cmd: "reasoning", level: it.level, default: true } : { cmd: "reasoning", level: it.level });
|
|
86531
86531
|
};
|
|
86532
86532
|
if (key.leftArrow || key.upArrow) setPicker((p) => ({ ...p, index: (p.index + p.items.length - 1) % p.items.length }));
|
|
86533
86533
|
else if (key.rightArrow || key.downArrow || key.tab) setPicker((p) => ({ ...p, index: (p.index + 1) % p.items.length }));
|
|
@@ -86542,7 +86542,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86542
86542
|
setPicker(null);
|
|
86543
86543
|
if (it.current) return;
|
|
86544
86544
|
modelRef.current = it.name;
|
|
86545
|
-
|
|
86545
|
+
core2.send({ cmd: "model", name: it.name });
|
|
86546
86546
|
};
|
|
86547
86547
|
if (key.upArrow) setPicker((p) => ({ ...p, index: (p.index + p.items.length - 1) % p.items.length }));
|
|
86548
86548
|
else if (key.downArrow || key.tab) setPicker((p) => ({ ...p, index: (p.index + 1) % p.items.length }));
|
|
@@ -86569,7 +86569,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86569
86569
|
setPicker(null);
|
|
86570
86570
|
if (it.live && it.live.here) {
|
|
86571
86571
|
} else if (it.live && it.live.port) attachTo(it.live.port, it.live.run_id);
|
|
86572
|
-
else
|
|
86572
|
+
else core2.send({ cmd: "resume", name: it.name });
|
|
86573
86573
|
} else if (key.ctrl && input === "a") setPicker((p) => ({ ...p, scope: p.scope === "here" ? "all" : "here", index: 0, top: 0 }));
|
|
86574
86574
|
else if (key.backspace || key.delete) setPicker((p) => ({ ...p, query: p.query.slice(0, -1), index: 0, top: 0 }));
|
|
86575
86575
|
else if (input && !key.ctrl && !key.meta && input >= " ") setPicker((p) => ({ ...p, query: p.query + input, index: 0, top: 0 }));
|
|
@@ -86583,14 +86583,14 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86583
86583
|
}
|
|
86584
86584
|
if (key.escape) {
|
|
86585
86585
|
if (phaseRef.current === "busy") {
|
|
86586
|
-
|
|
86586
|
+
core2.send({ cmd: "interrupt" });
|
|
86587
86587
|
escRef.current = 0;
|
|
86588
86588
|
return;
|
|
86589
86589
|
}
|
|
86590
86590
|
const now = Date.now();
|
|
86591
86591
|
if (now - escRef.current < ESC_ESC_MS) {
|
|
86592
86592
|
escRef.current = 0;
|
|
86593
|
-
|
|
86593
|
+
core2.send({ cmd: "rewind_list" });
|
|
86594
86594
|
return;
|
|
86595
86595
|
}
|
|
86596
86596
|
escRef.current = now;
|
|
@@ -86604,7 +86604,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86604
86604
|
helloRef.current = false;
|
|
86605
86605
|
setPhaseBoth("connecting");
|
|
86606
86606
|
const token2 = (readRun(runId || "") || {}).token || "";
|
|
86607
|
-
|
|
86607
|
+
core2.reconnect(port2, token2).catch((e) => {
|
|
86608
86608
|
append({ kind: "error", text: `could not attach: ${e.message}` });
|
|
86609
86609
|
setPhaseBoth("idle");
|
|
86610
86610
|
});
|
|
@@ -86616,7 +86616,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86616
86616
|
const what = p && p.calls.length ? p.calls.map((c) => c.desc).join(" \xB7 ") : "the proposal";
|
|
86617
86617
|
const also = remember ? ` \xB7 ${p.remember_text || "that shape"} allowed for ${remember === "session" ? "this session" : "this project"}` : "";
|
|
86618
86618
|
append({ kind: "you", text: decision === "accept" ? `approved: ${what}${also}` : `rejected: ${what}${note ? ` \u2014 ${note}` : ""}` });
|
|
86619
|
-
|
|
86619
|
+
core2.send({ cmd: "decide", decision, note: note || "", ...remember ? { remember } : {} });
|
|
86620
86620
|
};
|
|
86621
86621
|
const togglePick = (label) => {
|
|
86622
86622
|
setValue("");
|
|
@@ -86635,10 +86635,10 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86635
86635
|
return;
|
|
86636
86636
|
}
|
|
86637
86637
|
dropAsk(question.id);
|
|
86638
|
-
|
|
86638
|
+
core2.send({ cmd: "answer", id: question.id, answers });
|
|
86639
86639
|
};
|
|
86640
86640
|
const vote = (polarity, why2 = "") => {
|
|
86641
|
-
|
|
86641
|
+
core2.send({ cmd: polarity > 0 ? "accept" : "reject", ...why2 ? { why: why2 } : {} });
|
|
86642
86642
|
setOffer(false);
|
|
86643
86643
|
};
|
|
86644
86644
|
const runCommand = (line) => {
|
|
@@ -86660,27 +86660,27 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86660
86660
|
append({ kind: "info", text: HELP });
|
|
86661
86661
|
break;
|
|
86662
86662
|
case "/resume":
|
|
86663
|
-
|
|
86663
|
+
core2.send({ cmd: "sessions" });
|
|
86664
86664
|
break;
|
|
86665
86665
|
case "/compact":
|
|
86666
|
-
|
|
86666
|
+
core2.send(arg ? { cmd: "compact", text: arg } : { cmd: "compact" });
|
|
86667
86667
|
break;
|
|
86668
86668
|
case "/model":
|
|
86669
86669
|
if (arg) {
|
|
86670
86670
|
modelRef.current = arg;
|
|
86671
|
-
|
|
86672
|
-
} else
|
|
86671
|
+
core2.send({ cmd: "model", name: arg });
|
|
86672
|
+
} else core2.send({ cmd: "model" });
|
|
86673
86673
|
break;
|
|
86674
86674
|
case "/reasoning":
|
|
86675
|
-
if (arg)
|
|
86676
|
-
else
|
|
86675
|
+
if (arg) core2.send({ cmd: "reasoning", level: arg });
|
|
86676
|
+
else core2.send({ cmd: "reasoning" });
|
|
86677
86677
|
break;
|
|
86678
86678
|
case "/diff":
|
|
86679
|
-
|
|
86679
|
+
core2.send({ cmd: "diff", scope: arg });
|
|
86680
86680
|
break;
|
|
86681
86681
|
case "/rewind":
|
|
86682
86682
|
wantRow.current = /^\d+$/.test(arg) ? Number(arg) : null;
|
|
86683
|
-
|
|
86683
|
+
core2.send({ cmd: "rewind_list" });
|
|
86684
86684
|
break;
|
|
86685
86685
|
case "/cost": {
|
|
86686
86686
|
const ctx = ctxPct > 0 ? ` \xB7 context ${ctxPct}% of the compaction threshold` : "";
|
|
@@ -86690,14 +86690,14 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86690
86690
|
case "/image":
|
|
86691
86691
|
if (!hello?.images) append({ kind: "warn", text: "this version of hum does not take images; update hum" });
|
|
86692
86692
|
else if (!arg) append({ kind: "info", text: "/image <path> attaches the file to your next message \xB7 ctrl+v pastes a screenshot \xB7 @path.png in a message works too" });
|
|
86693
|
-
else
|
|
86693
|
+
else core2.send({ cmd: "attach", path: arg });
|
|
86694
86694
|
break;
|
|
86695
86695
|
case "/tools":
|
|
86696
86696
|
append({ kind: "info", text: `${(hello?.tools || []).join(", ")} \xB7 sandbox: ${hello?.sandbox || "none"}` });
|
|
86697
86697
|
break;
|
|
86698
86698
|
case "/mcp":
|
|
86699
86699
|
if (hello?.mcp === void 0) append({ kind: "warn", text: "this version of hum does not say what is mounted; update hum (/stop, then hum)" });
|
|
86700
|
-
else
|
|
86700
|
+
else core2.send({ cmd: "mcp" });
|
|
86701
86701
|
break;
|
|
86702
86702
|
case "/accept":
|
|
86703
86703
|
vote(1, arg);
|
|
@@ -86705,28 +86705,28 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86705
86705
|
case "/reject":
|
|
86706
86706
|
vote(-1, arg);
|
|
86707
86707
|
break;
|
|
86708
|
-
case "/
|
|
86709
|
-
|
|
86708
|
+
case "/slack":
|
|
86709
|
+
core2.send({ cmd: "slack" });
|
|
86710
86710
|
break;
|
|
86711
|
-
// the
|
|
86711
|
+
// the core's words: the session's Slack surface
|
|
86712
86712
|
case "/hooks":
|
|
86713
|
-
|
|
86713
|
+
core2.send({ cmd: "hooks" });
|
|
86714
86714
|
break;
|
|
86715
86715
|
case "/usage-credits":
|
|
86716
|
-
|
|
86716
|
+
core2.send({ cmd: "credits" });
|
|
86717
86717
|
break;
|
|
86718
86718
|
case "/permissions":
|
|
86719
|
-
|
|
86719
|
+
core2.send({ cmd: "permissions" });
|
|
86720
86720
|
break;
|
|
86721
86721
|
case "/continue":
|
|
86722
|
-
|
|
86722
|
+
core2.send({ cmd: "continue" });
|
|
86723
86723
|
break;
|
|
86724
86724
|
case "/goal":
|
|
86725
|
-
|
|
86725
|
+
core2.send(arg ? { cmd: "goal", text: arg } : { cmd: "goal" });
|
|
86726
86726
|
break;
|
|
86727
86727
|
case "/approve": {
|
|
86728
86728
|
const mode = arg === "on" ? "approve" : arg === "off" ? "off" : gate === "approve" ? "off" : "approve";
|
|
86729
|
-
|
|
86729
|
+
core2.send({ cmd: "gate", mode });
|
|
86730
86730
|
break;
|
|
86731
86731
|
}
|
|
86732
86732
|
default:
|
|
@@ -86734,7 +86734,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86734
86734
|
}
|
|
86735
86735
|
};
|
|
86736
86736
|
const closeReflection = (id, vote2, reason = "") => {
|
|
86737
|
-
|
|
86737
|
+
core2.send({ cmd: "reflect_vote", id, vote: vote2, ...reason ? { why: reason } : {} });
|
|
86738
86738
|
setReflections((rs) => rs.filter((r) => r.id !== id));
|
|
86739
86739
|
setWhy((w) => w === id ? null : w);
|
|
86740
86740
|
setValue("");
|
|
@@ -86780,14 +86780,14 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
86780
86780
|
}
|
|
86781
86781
|
if (text.startsWith("!")) {
|
|
86782
86782
|
append({ kind: "you", text });
|
|
86783
|
-
|
|
86783
|
+
core2.send({ cmd: "shell", command: text.slice(1).trim() });
|
|
86784
86784
|
if (phaseRef.current === "idle") setPhaseBoth("busy");
|
|
86785
86785
|
return;
|
|
86786
86786
|
}
|
|
86787
86787
|
if (paused) setPaused(false);
|
|
86788
86788
|
if (dropped.length) append({ kind: "info", text: `not sent (chip removed): ${dropped.map((a) => a.label).join(", ")}` });
|
|
86789
86789
|
append({ kind: "you", text, images: attached.map((a) => `#${a.n} ${a.label}`), steering: phaseRef.current === "busy" });
|
|
86790
|
-
|
|
86790
|
+
core2.send({ cmd: "message", text, images: attached.map((a) => a.ref) });
|
|
86791
86791
|
attachRef.current = [];
|
|
86792
86792
|
if (phaseRef.current === "idle") {
|
|
86793
86793
|
turnT0.current = Date.now();
|
|
@@ -87272,7 +87272,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
87272
87272
|
input_default,
|
|
87273
87273
|
{
|
|
87274
87274
|
ref: inputRef,
|
|
87275
|
-
onPasteImage: () => hello?.images ?
|
|
87275
|
+
onPasteImage: () => hello?.images ? core2.send({ cmd: "paste_image" }) : append({ kind: "warn", text: "this version of hum does not take images; update hum" }),
|
|
87276
87276
|
value,
|
|
87277
87277
|
onChange: setValue,
|
|
87278
87278
|
onSubmit,
|
|
@@ -87303,7 +87303,7 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
87303
87303
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "tab to complete \xB7 enter to run" })
|
|
87304
87304
|
] }),
|
|
87305
87305
|
!menu.length && agents.length > 0 && // one flat list: ○ a sub-agent of this process, ◇ a worker session of the team (its state, what it needs,
|
|
87306
|
-
// +N sub-agents of its own); the
|
|
87306
|
+
// +N sub-agents of its own); the core puts what wants a person first. ↓ moves a highlight in from the box
|
|
87307
87307
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", paddingX: 1, children: [
|
|
87308
87308
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
|
|
87309
87309
|
" ",
|
|
@@ -87351,22 +87351,22 @@ function App2({ engine: engine2, task, resume, images = [], peek = peekSession,
|
|
|
87351
87351
|
}
|
|
87352
87352
|
|
|
87353
87353
|
// src/cli.jsx
|
|
87354
|
-
|
|
87354
|
+
init_core();
|
|
87355
87355
|
init_update();
|
|
87356
87356
|
init_install();
|
|
87357
87357
|
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
|
87358
87358
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
87359
|
-
var MINE2 = true ? "0.1.
|
|
87359
|
+
var MINE2 = true ? "0.1.76" : "0.0.0";
|
|
87360
87360
|
var layout = installLayout();
|
|
87361
87361
|
function completeInstall() {
|
|
87362
87362
|
if (layout.kind !== "npm" || !needsInstall(MINE2)) return;
|
|
87363
87363
|
const say = (m) => process.stderr.write(`hum: ${m}
|
|
87364
87364
|
`);
|
|
87365
87365
|
say(`updating to ${MINE2} \u2026`);
|
|
87366
|
-
const r =
|
|
87366
|
+
const r = installCore(MINE2, { say });
|
|
87367
87367
|
if (!r.ok) say(`the update did not finish: ${r.error} \xB7 ${npmFix(MINE2)}`);
|
|
87368
87368
|
}
|
|
87369
|
-
var
|
|
87369
|
+
var CORE_COMMANDS = /* @__PURE__ */ new Set(["run", "login", "logout", "whoami", "model", "key", "sessions", "show", "sync", "skill", "persona", "ps", "stop", "hooks", "core"]);
|
|
87370
87370
|
var argv0 = process.argv.slice(2);
|
|
87371
87371
|
if (argv0[0] === "--version" || argv0[0] === "-V") {
|
|
87372
87372
|
process.stdout.write(`hum ${MINE2}
|
|
@@ -87384,9 +87384,9 @@ if (argv0[0] === "doctor") {
|
|
|
87384
87384
|
const { doctor: doctor2 } = await Promise.resolve().then(() => (init_doctor(), doctor_exports));
|
|
87385
87385
|
process.exit(await doctor2({ json: argv0.includes("--json"), mine: MINE2, layout }));
|
|
87386
87386
|
}
|
|
87387
|
-
if (
|
|
87387
|
+
if (CORE_COMMANDS.has(argv0[0]) || argv0[0] === "agents" && argv0.includes("--json") || wantsPlain(argv0)) {
|
|
87388
87388
|
completeInstall();
|
|
87389
|
-
const cmd =
|
|
87389
|
+
const cmd = coreCommand(argv0);
|
|
87390
87390
|
if (!cmd) {
|
|
87391
87391
|
process.stderr.write(startFailure([]) + "\n");
|
|
87392
87392
|
process.exit(1);
|
|
@@ -87398,8 +87398,8 @@ if (ENGINE_COMMANDS.has(argv0[0]) || argv0[0] === "agents" && argv0.includes("--
|
|
|
87398
87398
|
}
|
|
87399
87399
|
process.exit(r.status === null ? 1 : r.status);
|
|
87400
87400
|
}
|
|
87401
|
-
function leave(
|
|
87402
|
-
|
|
87401
|
+
function leave(core2) {
|
|
87402
|
+
core2.close();
|
|
87403
87403
|
process.exit(0);
|
|
87404
87404
|
}
|
|
87405
87405
|
if (argv0[0] === "agents") {
|
|
@@ -87421,16 +87421,16 @@ if (argv0[0] === "agents") {
|
|
|
87421
87421
|
}, onQuit: () => screen.unmount() }));
|
|
87422
87422
|
await screen.waitUntilExit();
|
|
87423
87423
|
if (!chosen) process.exit(0);
|
|
87424
|
-
const
|
|
87424
|
+
const core2 = new Core(chosen.port, (readRun(chosen.run_id) || {}).token || "");
|
|
87425
87425
|
try {
|
|
87426
|
-
await
|
|
87426
|
+
await core2.connect();
|
|
87427
87427
|
} catch (exc) {
|
|
87428
87428
|
process.stderr.write(exc.message + "\n");
|
|
87429
87429
|
process.exit(1);
|
|
87430
87430
|
}
|
|
87431
|
-
const app = render_default(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(App2, {
|
|
87431
|
+
const app = render_default(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(App2, { core: core2, task: null, resume: null, images: [] }), { exitOnCtrlC: false });
|
|
87432
87432
|
await app.waitUntilExit();
|
|
87433
|
-
leave(
|
|
87433
|
+
leave(core2);
|
|
87434
87434
|
}
|
|
87435
87435
|
function parseArgs(argv) {
|
|
87436
87436
|
const a = { task: null, resume: null, cwd: process.cwd(), images: [] };
|
|
@@ -87456,13 +87456,13 @@ if (!process.stdin.isTTY) {
|
|
|
87456
87456
|
process.stderr.write('hum needs an interactive terminal; use `hum run "task"` when piping.\n');
|
|
87457
87457
|
process.exit(1);
|
|
87458
87458
|
}
|
|
87459
|
-
var port = Number(process.env.
|
|
87459
|
+
var port = Number(process.env.HUM_CORE_PORT || 0);
|
|
87460
87460
|
var token = port ? (readRun(process.env.HUM_RUN_ID || "") || {}).token || "" : "";
|
|
87461
87461
|
var startedHere = false;
|
|
87462
87462
|
try {
|
|
87463
87463
|
if (!port) {
|
|
87464
87464
|
completeInstall();
|
|
87465
|
-
const rec = await
|
|
87465
|
+
const rec = await spawnCore(args.cwd, { task: args.task, images: args.images, resume: args.resume && args.resume !== "pick" ? args.resume : null });
|
|
87466
87466
|
startedHere = true;
|
|
87467
87467
|
port = rec.port;
|
|
87468
87468
|
token = rec.token || "";
|
|
@@ -87474,15 +87474,15 @@ try {
|
|
|
87474
87474
|
}
|
|
87475
87475
|
throw exc;
|
|
87476
87476
|
}
|
|
87477
|
-
var
|
|
87477
|
+
var core = new Core(port, token);
|
|
87478
87478
|
try {
|
|
87479
|
-
await
|
|
87479
|
+
await core.connect();
|
|
87480
87480
|
} catch (exc) {
|
|
87481
87481
|
process.stderr.write(exc.message + "\n");
|
|
87482
87482
|
process.exit(1);
|
|
87483
87483
|
}
|
|
87484
|
-
var { waitUntilExit } = render_default(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(App2, {
|
|
87485
|
-
waitUntilExit().then(() => leave(
|
|
87484
|
+
var { waitUntilExit } = render_default(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(App2, { core, task: startedHere ? null : args.task, resume: args.resume === "pick" || !startedHere ? args.resume : null, images: startedHere ? [] : args.images }), { exitOnCtrlC: false });
|
|
87485
|
+
waitUntilExit().then(() => leave(core));
|
|
87486
87486
|
/*! Bundled license information:
|
|
87487
87487
|
|
|
87488
87488
|
react/cjs/react.production.min.js:
|
package/dist/install.mjs
CHANGED
|
@@ -7,14 +7,14 @@ var win = process.platform === "win32";
|
|
|
7
7
|
var npmFix = (version = "") => `npm i -g @metaphi-ai/hum@${version || "latest"} --foreground-scripts`;
|
|
8
8
|
var NPM_FIX = npmFix("latest");
|
|
9
9
|
var humHome = (env = process.env) => env.HUM_HOME || path.join(os.homedir(), ".hum");
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
var stampPath = (env) => path.join(
|
|
13
|
-
var statePath = (env) => path.join(humHome(env), "
|
|
10
|
+
var coreDir = (env = process.env) => path.join(humHome(env), "core");
|
|
11
|
+
var corePython = (env = process.env) => win ? path.join(coreDir(env), "Scripts", "python.exe") : path.join(coreDir(env), "bin", "python");
|
|
12
|
+
var stampPath = (env) => path.join(coreDir(env), "version");
|
|
13
|
+
var statePath = (env) => path.join(humHome(env), "core-install.json");
|
|
14
14
|
var run = (cmd, args, opts = {}) => spawnSync(cmd, args, { encoding: "utf8", windowsHide: true, ...opts });
|
|
15
15
|
var ASK_VERSION = ["-I", "-c", "import hum; print(hum.__version__)"];
|
|
16
16
|
function importedVersion(env = process.env, runImpl = run) {
|
|
17
|
-
const r = runImpl(
|
|
17
|
+
const r = runImpl(corePython(env), ASK_VERSION);
|
|
18
18
|
return r && r.status === 0 ? String(r.stdout).trim() : null;
|
|
19
19
|
}
|
|
20
20
|
function installedVersion(env = process.env, runImpl = run) {
|
|
@@ -22,7 +22,7 @@ function installedVersion(env = process.env, runImpl = run) {
|
|
|
22
22
|
return fs.readFileSync(stampPath(env), "utf8").trim() || null;
|
|
23
23
|
} catch {
|
|
24
24
|
}
|
|
25
|
-
if (!fs.existsSync(
|
|
25
|
+
if (!fs.existsSync(corePython(env))) return null;
|
|
26
26
|
const v = importedVersion(env, runImpl);
|
|
27
27
|
if (v) {
|
|
28
28
|
try {
|
|
@@ -41,12 +41,12 @@ function trustedPython(env = process.env, runImpl = run) {
|
|
|
41
41
|
}
|
|
42
42
|
var ASK_SSL = ["-I", "-c", "import ssl"];
|
|
43
43
|
function sslBlocked(env = process.env, runImpl = run) {
|
|
44
|
-
const r = runImpl(
|
|
44
|
+
const r = runImpl(corePython(env), ASK_SSL);
|
|
45
45
|
if (r && r.status === 0) return null;
|
|
46
46
|
const text = String(r && (r.stderr || r.stdout) || "ssl did not import").trim().split(/\r?\n/).filter(Boolean).pop() || "ssl did not import";
|
|
47
47
|
return text;
|
|
48
48
|
}
|
|
49
|
-
var sslAdvice = (env, version) => `the machine's application control blocked Python's OpenSSL DLL in ${
|
|
49
|
+
var sslAdvice = (env, version) => `the machine's application control blocked Python's OpenSSL DLL in ${coreDir(env)}; install Python 3.12 from python.org (Microsoft signs it), then run ${npmFix(version)}`;
|
|
50
50
|
var readInstallState = (env = process.env) => {
|
|
51
51
|
try {
|
|
52
52
|
return JSON.parse(fs.readFileSync(statePath(env), "utf8"));
|
|
@@ -62,22 +62,22 @@ var writeInstallState = (s, env) => {
|
|
|
62
62
|
}
|
|
63
63
|
};
|
|
64
64
|
function needsInstall(version, { env = process.env, installed = () => installedVersion(env), now = Date.now(), state = readInstallState(env) } = {}) {
|
|
65
|
-
if (!version || env.
|
|
65
|
+
if (!version || env.HUM_CORE || env.HUM_CORE_PORT) return false;
|
|
66
66
|
if (installed() === version) return false;
|
|
67
67
|
if (state && !state.ok && state.version === version && now - (state.at || 0) < 10 * 60 * 1e3) return false;
|
|
68
68
|
return true;
|
|
69
69
|
}
|
|
70
|
-
function
|
|
70
|
+
function installCore(version, { env = process.env, say = (m) => console.log(`hum: ${m}`), runImpl = run, now = Date.now() } = {}) {
|
|
71
71
|
const home = humHome(env);
|
|
72
|
-
const dir =
|
|
73
|
-
const python =
|
|
72
|
+
const dir = coreDir(env);
|
|
73
|
+
const python = corePython(env);
|
|
74
74
|
const localBin = path.join(os.homedir(), ".local", "bin");
|
|
75
75
|
const uvNames = ["uv", path.join(localBin, win ? "uv.exe" : "uv")];
|
|
76
76
|
const uv = () => uvNames.find((u) => {
|
|
77
77
|
const r = runImpl(u, ["--version"]);
|
|
78
78
|
return r && r.status === 0;
|
|
79
79
|
});
|
|
80
|
-
const spec = env.
|
|
80
|
+
const spec = env.HUM_CORE_SPEC || `hum-cli==${version}`;
|
|
81
81
|
const outcome = (ok, error = null, got = version) => {
|
|
82
82
|
writeInstallState({ version: got, wanted: version, ok, error, at: now }, env);
|
|
83
83
|
return { ok, version: got, error };
|
|
@@ -90,7 +90,7 @@ function installEngine(version, { env = process.env, say = (m) => console.log(`h
|
|
|
90
90
|
u = r && r.status === 0 ? uv() : null;
|
|
91
91
|
if (!u) return outcome(false, `could not install uv; install it from https://astral.sh/uv and run: ${npmFix(version)}`);
|
|
92
92
|
}
|
|
93
|
-
say(`installing ${env.
|
|
93
|
+
say(`installing ${env.HUM_CORE_SPEC ? spec : `hum ${version}`} into ${dir} \u2026`);
|
|
94
94
|
fs.mkdirSync(home, { recursive: true });
|
|
95
95
|
try {
|
|
96
96
|
fs.unlinkSync(stampPath(env));
|
|
@@ -103,7 +103,7 @@ function installEngine(version, { env = process.env, say = (m) => console.log(`h
|
|
|
103
103
|
if (!pipIn()) return outcome(false, `uv pip install ${spec} failed`);
|
|
104
104
|
let got = importedVersion(env, runImpl);
|
|
105
105
|
if (!got) return outcome(false, "hum did not import after the install");
|
|
106
|
-
if (got !== version && !env.
|
|
106
|
+
if (got !== version && !env.HUM_CORE_SPEC) return outcome(false, `installed ${got}, wanted ${version}`, got);
|
|
107
107
|
let blocked = sslBlocked(env, runImpl);
|
|
108
108
|
if (blocked && trusted) {
|
|
109
109
|
say(`the policy here refuses the environment's OpenSSL (${blocked}); rebuilding it on ${trusted} \u2026`);
|
|
@@ -131,11 +131,11 @@ export {
|
|
|
131
131
|
ASK_SSL,
|
|
132
132
|
ASK_VERSION,
|
|
133
133
|
NPM_FIX,
|
|
134
|
-
|
|
135
|
-
|
|
134
|
+
coreDir,
|
|
135
|
+
corePython,
|
|
136
136
|
humHome,
|
|
137
137
|
importedVersion,
|
|
138
|
-
|
|
138
|
+
installCore,
|
|
139
139
|
installedVersion,
|
|
140
140
|
needsInstall,
|
|
141
141
|
npmFix,
|
package/package.json
CHANGED
package/scripts/postinstall.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// npm's postinstall: complete the install at this package's version. The work is in
|
|
2
2
|
// dist/install.mjs — the same code `hum` runs at start when the two halves differ — and the
|
|
3
|
-
// outcome lands in ~/.hum/
|
|
3
|
+
// outcome lands in ~/.hum/core-install.json, because npm shows none of this unless it is
|
|
4
4
|
// run with --foreground-scripts. Never fails the npm install.
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
@@ -9,9 +9,9 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
9
9
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
const version = JSON.parse(fs.readFileSync(path.join(here, '..', 'package.json'), 'utf8')).version;
|
|
11
11
|
// a URL, not a path: on Windows `C:\…` is not something the ESM loader will import
|
|
12
|
-
const { installedVersion,
|
|
12
|
+
const { installedVersion, installCore, npmFix } = await import(pathToFileURL(path.join(here, '..', 'dist', 'install.mjs')).href);
|
|
13
13
|
|
|
14
14
|
if (installedVersion() !== version) {
|
|
15
|
-
const r =
|
|
15
|
+
const r = installCore(version);
|
|
16
16
|
if (!r.ok) console.log(`hum: the install did not finish (${r.error}); run: ${npmFix(version)}`);
|
|
17
17
|
}
|