@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- // `hum` from npm: the Ink front-end, which starts Hum's engine (Python, installed by postinstall
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 engine.
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(enginePython(env3), ASK_VERSION);
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(enginePython(env3))) return null;
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(enginePython(env3), ASK_SSL);
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.HUM_ENGINE || env3.HUM_ENGINE_PORT) return false;
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 installEngine(version, { env: env3 = process.env, say = (m) => console.log(`hum: ${m}`), runImpl = run, now = Date.now() } = {}) {
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 = engineDir(env3);
83238
- const python = enginePython(env3);
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.HUM_ENGINE_SPEC || `hum-cli==${version}`;
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.HUM_ENGINE_SPEC ? spec : `hum ${version}`} into ${dir} \u2026`);
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.HUM_ENGINE_SPEC) return outcome(false, `installed ${got}, wanted ${version}`, got);
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, engineDir, enginePython, stampPath, statePath, run, ASK_VERSION, ASK_SSL, sslAdvice, readInstallState, writeInstallState;
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
- engineDir = (env3 = process.env) => path.join(humHome(env3), "engine");
83303
- enginePython = (env3 = process.env) => win ? path.join(engineDir(env3), "Scripts", "python.exe") : path.join(engineDir(env3), "bin", "python");
83304
- stampPath = (env3) => path.join(engineDir(env3), "version");
83305
- statePath = (env3) => path.join(humHome(env3), "engine-install.json");
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 ${engineDir(env3)}; install Python 3.12 from python.org (Microsoft signs it), then run ${npmFix(version)}`;
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.HUM_ENGINE_PORT ? "python" : "npm" };
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.HUM_ENGINE) return `${head}: HUM_ENGINE points at it \xB7 unset HUM_ENGINE to use ${mine}`;
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/engine.js
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 enginePython2(dirs = uvToolDirs()) {
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 siblingEngine(execPath = process.execPath) {
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, "engine", win3 ? "hum-engine.exe" : "hum-engine");
83528
+ const p = path3.join(dir, "core", win3 ? "hum-core.exe" : "hum-core");
83529
83529
  return exists(p) ? p : null;
83530
83530
  }
83531
- function homeEngine(env3 = process.env) {
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, "engine", "Scripts", "python.exe") : path3.join(home, "engine", "bin", "python");
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 engineCandidates(env3 = process.env) {
83536
+ function coreCandidates(env3 = process.env) {
83537
83537
  const out = [];
83538
- if (env3.HUM_ENGINE) {
83539
- const [bin, ...args2] = env3.HUM_ENGINE.split(" ");
83540
- out.push({ bin, args: args2, where: "HUM_ENGINE" });
83541
- }
83542
- const sib = siblingEngine();
83543
- if (sib) out.push({ bin: sib, args: ["engine"], where: "beside hum" });
83544
- const home = homeEngine(env3);
83545
- if (home) out.push({ bin: home, args: ["-m", "hum.cli", "engine"], where: "HUM_HOME/engine" });
83546
- const py = enginePython2();
83547
- if (py) out.push({ bin: py, args: ["-m", "hum.cli", "engine"], where: "the interpreter beside it" });
83548
- out.push({ bin: "hum-engine", args: [], where: "PATH" });
83549
- out.push({ bin: path3.join(os5.homedir(), ".local", "bin", win3 ? "hum-engine.exe" : "hum-engine"), args: [], where: "uv's bin dir" });
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 engineCommand(argv, candidates = engineCandidates()) {
83555
+ function coreCommand(argv, candidates = coreCandidates()) {
83556
83556
  for (const c of candidates) {
83557
- if (c.args[c.args.length - 1] !== "engine") continue;
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/engine") return installedVersion(env3);
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 = engineCandidates(), opts = {}) {
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.74" : "" } = {}) {
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 HUM_ENGINE to the command that runs it)`;
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 HUM_ENGINE=${path3.join(dir || "<uv tool dir>", "hum-cli", "Scripts", "python.exe")} -m hum.cli engine`);
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 HUM_ENGINE to a command that starts it, e.g. HUM_ENGINE="python -m hum.cli engine"');
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 spawnEngine(cwd2, { task = null, images = [], resume = null, candidates = engineCandidates() } = {}) {
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, Engine;
83694
- var init_engine = __esm({
83695
- "src/engine.js"() {
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
- Engine = class {
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 engine counts it as
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 engine reads before it says anything back.
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 engine (a session running elsewhere on this machine): its token comes
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 Engine(port2, token2)) {
83939
+ async function peekSession(row, ready, make = (port2, token2) => new Core(port2, token2)) {
83940
83940
  const token2 = (readRun(row.run_id) || {}).token || "";
83941
- const engine2 = make(row.port, token2);
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
- engine2.on((ev) => {
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 engine2.connect();
83958
+ await core2.connect();
83959
83959
  return {
83960
- answer: (id, text) => engine2.send({ cmd: "answer", id, text }),
83960
+ answer: (id, text) => core2.send({ cmd: "answer", id, text }),
83961
83961
  close: () => {
83962
83962
  clearTimeout(timer);
83963
- engine2.close();
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
- init_engine();
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-engine.exe", "hum-engine.cmd"] : ["hum", "hum-engine"];
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 = engineCandidates(env3),
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-engine"));
84980
- const stale = hits.filter((h) => h.name.startsWith("hum-engine"));
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.HUM_ENGINE_PORT) checks.push(check("ok", `started by Python for this hum (HUM_ENGINE_PORT=${env3.HUM_ENGINE_PORT})`));
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.HUM_ENGINE) checks.push(check("fail", `${running.version} is what runs: HUM_ENGINE points at it (${env3.HUM_ENGINE}); you installed ${mine}`, "unset HUM_ENGINE"));
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.HUM_ENGINE && running && running.version === mine) checks.push(check("warn", `HUM_ENGINE is set (${env3.HUM_ENGINE}): it decides what runs, ahead of any install`, "unset HUM_ENGINE"));
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 ${engineDir(env3)}`, npmFix2(mine)));
85021
- else checks.push(check(stamp === mine ? "ok" : "warn", `${engineDir(env3)} holds ${stamp}`, stamp === mine ? "" : npmFix2(mine)));
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, "engine", isWin(platform2) ? "hum-engine.exe" : "hum-engine");
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(enginePython(env3)) ? enginePython(env3) : null;
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, "engine-install.json")]) {
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
- init_engine();
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
- init_engine();
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.74" : "";
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: "/comms", desc: "the channels in the loop on this session (Slack), and whether you are paired" },
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({ engine: engine2, task, resume, images = [], peek = peekSession, update = updateNotice, watch = watchReady }) {
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") engine2.send({ cmd: "sessions" });
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
- engine2.send({ cmd: "start", task, images: ev.images ? images : [] });
85987
+ core2.send({ cmd: "start", task, images: ev.images ? images : [] });
85988
85988
  } else if (resume === "pick") {
85989
85989
  setPhaseBoth("idle");
85990
- engine2.send({ cmd: "sessions" });
85991
- } else if (resume) engine2.send({ cmd: "resume", name: 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) => engine2.send({ cmd: "attach", path: 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
- engine2.on(handle);
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
- engine2.send({ cmd: "quit" });
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
- engine2.send({ cmd: "stop" });
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") engine2.send({ cmd: "interrupt" });
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
- engine2.send({ cmd: "rewind", to: confirm.node, ...rewindRef.current, confirm: true });
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
- engine2.send({ cmd: "rewind", to: it.node, ...rewindRef.current });
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
- engine2.send({ cmd: "interrupt" });
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
- engine2.send(keep ? { cmd: "reasoning", level: it.level, default: true } : { cmd: "reasoning", level: it.level });
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
- engine2.send({ cmd: "model", name: it.name });
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 engine2.send({ cmd: "resume", name: it.name });
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
- engine2.send({ cmd: "interrupt" });
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
- engine2.send({ cmd: "rewind_list" });
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
- engine2.reconnect(port2, token2).catch((e) => {
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
- engine2.send({ cmd: "decide", decision, note: note || "", ...remember ? { remember } : {} });
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
- engine2.send({ cmd: "answer", id: question.id, answers });
86638
+ core2.send({ cmd: "answer", id: question.id, answers });
86639
86639
  };
86640
86640
  const vote = (polarity, why2 = "") => {
86641
- engine2.send({ cmd: polarity > 0 ? "accept" : "reject", ...why2 ? { why: why2 } : {} });
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
- engine2.send({ cmd: "sessions" });
86663
+ core2.send({ cmd: "sessions" });
86664
86664
  break;
86665
86665
  case "/compact":
86666
- engine2.send(arg ? { cmd: "compact", text: arg } : { cmd: "compact" });
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
- engine2.send({ cmd: "model", name: arg });
86672
- } else engine2.send({ cmd: "model" });
86671
+ core2.send({ cmd: "model", name: arg });
86672
+ } else core2.send({ cmd: "model" });
86673
86673
  break;
86674
86674
  case "/reasoning":
86675
- if (arg) engine2.send({ cmd: "reasoning", level: arg });
86676
- else engine2.send({ cmd: "reasoning" });
86675
+ if (arg) core2.send({ cmd: "reasoning", level: arg });
86676
+ else core2.send({ cmd: "reasoning" });
86677
86677
  break;
86678
86678
  case "/diff":
86679
- engine2.send({ cmd: "diff", scope: arg });
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
- engine2.send({ cmd: "rewind_list" });
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 engine2.send({ cmd: "attach", path: arg });
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 engine2.send({ cmd: "mcp" });
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 "/comms":
86709
- engine2.send({ cmd: "comms" });
86708
+ case "/slack":
86709
+ core2.send({ cmd: "slack" });
86710
86710
  break;
86711
- // the engine's words: the channels in the loop here
86711
+ // the core's words: the session's Slack surface
86712
86712
  case "/hooks":
86713
- engine2.send({ cmd: "hooks" });
86713
+ core2.send({ cmd: "hooks" });
86714
86714
  break;
86715
86715
  case "/usage-credits":
86716
- engine2.send({ cmd: "credits" });
86716
+ core2.send({ cmd: "credits" });
86717
86717
  break;
86718
86718
  case "/permissions":
86719
- engine2.send({ cmd: "permissions" });
86719
+ core2.send({ cmd: "permissions" });
86720
86720
  break;
86721
86721
  case "/continue":
86722
- engine2.send({ cmd: "continue" });
86722
+ core2.send({ cmd: "continue" });
86723
86723
  break;
86724
86724
  case "/goal":
86725
- engine2.send(arg ? { cmd: "goal", text: arg } : { cmd: "goal" });
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
- engine2.send({ cmd: "gate", mode });
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
- engine2.send({ cmd: "reflect_vote", id, vote: vote2, ...reason ? { why: reason } : {} });
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
- engine2.send({ cmd: "shell", command: text.slice(1).trim() });
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
- engine2.send({ cmd: "message", text, images: attached.map((a) => a.ref) });
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 ? engine2.send({ cmd: "paste_image" }) : append({ kind: "warn", text: "this version of hum does not take images; update hum" }),
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 engine puts what wants a person first. ↓ moves a highlight in from the box
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
- init_engine();
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.74" : "0.0.0";
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 = installEngine(MINE2, { say });
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 ENGINE_COMMANDS = /* @__PURE__ */ new Set(["run", "login", "logout", "whoami", "model", "key", "sessions", "show", "sync", "skill", "persona", "ps", "stop", "hooks", "engine"]);
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 (ENGINE_COMMANDS.has(argv0[0]) || argv0[0] === "agents" && argv0.includes("--json") || wantsPlain(argv0)) {
87387
+ if (CORE_COMMANDS.has(argv0[0]) || argv0[0] === "agents" && argv0.includes("--json") || wantsPlain(argv0)) {
87388
87388
  completeInstall();
87389
- const cmd = engineCommand(argv0);
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(engine2) {
87402
- engine2.close();
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 engine2 = new Engine(chosen.port, (readRun(chosen.run_id) || {}).token || "");
87424
+ const core2 = new Core(chosen.port, (readRun(chosen.run_id) || {}).token || "");
87425
87425
  try {
87426
- await engine2.connect();
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, { engine: engine2, task: null, resume: null, images: [] }), { exitOnCtrlC: false });
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(engine2);
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.HUM_ENGINE_PORT || 0);
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 spawnEngine(args.cwd, { task: args.task, images: args.images, resume: args.resume && args.resume !== "pick" ? args.resume : null });
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 engine = new Engine(port, token);
87477
+ var core = new Core(port, token);
87478
87478
  try {
87479
- await engine.connect();
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, { engine, task: startedHere ? null : args.task, resume: args.resume === "pick" || !startedHere ? args.resume : null, images: startedHere ? [] : args.images }), { exitOnCtrlC: false });
87485
- waitUntilExit().then(() => leave(engine));
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 engineDir = (env = process.env) => path.join(humHome(env), "engine");
11
- var enginePython = (env = process.env) => win ? path.join(engineDir(env), "Scripts", "python.exe") : path.join(engineDir(env), "bin", "python");
12
- var stampPath = (env) => path.join(engineDir(env), "version");
13
- var statePath = (env) => path.join(humHome(env), "engine-install.json");
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(enginePython(env), ASK_VERSION);
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(enginePython(env))) return null;
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(enginePython(env), ASK_SSL);
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 ${engineDir(env)}; install Python 3.12 from python.org (Microsoft signs it), then run ${npmFix(version)}`;
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.HUM_ENGINE || env.HUM_ENGINE_PORT) return false;
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 installEngine(version, { env = process.env, say = (m) => console.log(`hum: ${m}`), runImpl = run, now = Date.now() } = {}) {
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 = engineDir(env);
73
- const python = enginePython(env);
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.HUM_ENGINE_SPEC || `hum-cli==${version}`;
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.HUM_ENGINE_SPEC ? spec : `hum ${version}`} into ${dir} \u2026`);
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.HUM_ENGINE_SPEC) return outcome(false, `installed ${got}, wanted ${version}`, got);
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
- engineDir,
135
- enginePython,
134
+ coreDir,
135
+ corePython,
136
136
  humHome,
137
137
  importedVersion,
138
- installEngine,
138
+ installCore,
139
139
  installedVersion,
140
140
  needsInstall,
141
141
  npmFix,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaphi-ai/hum",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "description": "Hum: a self-improving coding agent for your terminal.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",
@@ -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/engine-install.json, because npm shows none of this unless it is
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, installEngine, npmFix } = await import(pathToFileURL(path.join(here, '..', 'dist', 'install.mjs')).href);
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 = installEngine(version);
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
  }