@metaphi-ai/hum 0.1.71 → 0.1.73

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.
Files changed (2) hide show
  1. package/dist/cli.mjs +41 -122
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -83400,29 +83400,32 @@ function mismatchLine(mine, running, { env: env3 = process.env, layout: 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}`;
83402
83402
  }
83403
- function updateBox(mine, latest, notes = "", { env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3) } = {}) {
83404
- if (env3.HUM_NO_UPDATE_CHECK || !mine || !latest || !newer(latest, mine) || skipped(latest, env3)) return null;
83405
- const choices = UPDATE_CHOICES.map((c) => c.key === "later" && (env3.HUM_NO_AUTO_UPDATE || layout2.kind === "python") ? { ...c, desc: "keeps going on this version" } : c);
83406
- return { head: `Update available! ${mine} -> ${latest}`, latest, command: updateCommand(layout2), notes: notes || "", choices };
83407
- }
83408
- async function updateNotice(mine, { running = "", latest = "", env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3) } = {}) {
83403
+ function updateNotice(mine, { running = "", latest = "", env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3), spawnImpl = spawn, now = Date.now() } = {}) {
83409
83404
  const drift = mismatchLine(mine, running, { env: env3, layout: layout2 });
83410
83405
  if (drift) return drift;
83411
- if (env3.HUM_NO_UPDATE_CHECK || !latest || !newer(latest, mine) || layout2.kind === "python") return "";
83406
+ if (env3.HUM_NO_UPDATE_CHECK || !mine || !latest || !newer(latest, mine)) return "";
83407
+ if (env3.HUM_NO_AUTO_UPDATE || layout2.kind === "python") return `hum ${latest} is out \xB7 ${updateCommand(layout2)}`;
83412
83408
  if (readyVersion(layout2, latest)) return `hum ${latest} is ready \xB7 restart hum to use it`;
83413
- const s = readState(env3);
83414
- if (s.version === latest && !env3.HUM_NO_AUTO_UPDATE) return `hum ${latest} is still installing in the background (${path2.join(humHome2(env3), "update.log")} has the details)`;
83409
+ if (startBackgroundUpdate(latest, { env: env3, spawnImpl, layout: layout2, now })) return `hum ${latest} is installing in the background \xB7 it takes effect the next time you start hum`;
83410
+ if (readState(env3).version === latest) return `hum ${latest} is still installing in the background (${path2.join(humHome2(env3), "update.log")} has the details)`;
83415
83411
  return "";
83416
83412
  }
83417
- function updateDue(latest, { env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3), now = Date.now() } = {}) {
83418
- if (!latest || layout2.kind === "python") return !!latest;
83419
- if (readyVersion(layout2, latest)) return false;
83420
- const s = readState(env3);
83421
- return !(s.version === latest && !env3.HUM_NO_AUTO_UPDATE && now - (s.started || 0) < 30 * 60 * 1e3);
83422
- }
83423
- function laterNotice(latest, { env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3), spawnImpl = spawn } = {}) {
83424
- if (startBackgroundUpdate(latest, { env: env3, spawnImpl, layout: layout2 })) return `hum ${latest} is downloading in the background \xB7 it takes effect the next time you start hum`;
83425
- return "";
83413
+ function watchReady(latest, onReady, { env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3), every = 15e3, ready = readyVersion } = {}) {
83414
+ if (!latest || env3.HUM_NO_UPDATE_CHECK || env3.HUM_NO_AUTO_UPDATE || layout2.kind === "python") return () => {
83415
+ };
83416
+ if (ready(layout2, latest)) {
83417
+ onReady(latest, true);
83418
+ return () => {
83419
+ };
83420
+ }
83421
+ const t = setInterval(() => {
83422
+ if (ready(layout2, latest)) {
83423
+ clearInterval(t);
83424
+ onReady(latest, false);
83425
+ }
83426
+ }, every);
83427
+ if (t.unref) t.unref();
83428
+ return () => clearInterval(t);
83426
83429
  }
83427
83430
  function updateNow(layout2 = installLayout()) {
83428
83431
  if (layout2.kind === "native") {
@@ -83438,12 +83441,7 @@ function updateNow(layout2 = installLayout()) {
83438
83441
  const r = spawnSync2(win2() ? "npm.cmd" : "npm", ["i", "-g", "@metaphi-ai/hum@latest"], { stdio: "inherit", shell: win2() });
83439
83442
  return r.status ?? 1;
83440
83443
  }
83441
- function restart(argv = process.argv.slice(2), platform2 = process.platform) {
83442
- const w = platform2 === "win32";
83443
- const r = spawnSync2(w ? "hum.cmd" : "hum", argv, { stdio: "inherit", shell: w, windowsHide: true });
83444
- return r.error ? 1 : r.status ?? 1;
83445
- }
83446
- var dist, humHome2, win2, newer, updateCommand, readyVersion, stateFile, readState, writeState, skipVersion, skipped, UPDATE_CHOICES;
83444
+ var dist, humHome2, win2, newer, updateCommand, readyVersion, stateFile, readState, writeState;
83447
83445
  var init_update = __esm({
83448
83446
  "src/update.js"() {
83449
83447
  init_install();
@@ -83483,13 +83481,6 @@ var init_update = __esm({
83483
83481
  } catch {
83484
83482
  }
83485
83483
  };
83486
- skipVersion = (version, env3 = process.env) => writeState({ ...readState(env3), skipped: version }, env3);
83487
- skipped = (version, env3 = process.env) => !!version && readState(env3).skipped === version;
83488
- UPDATE_CHOICES = [
83489
- { key: "now", label: "Update now", desc: "installs and starts hum again on the new version" },
83490
- { key: "later", label: "Not now", desc: "keeps going \xB7 the new version installs in the background for next time" },
83491
- { key: "skip", label: "Skip this version", desc: "not offered again until the one after it" }
83492
- ];
83493
83484
  }
83494
83485
  });
83495
83486
 
@@ -83589,7 +83580,7 @@ function runningVersion(candidates = engineCandidates(), opts = {}) {
83589
83580
  }
83590
83581
  return null;
83591
83582
  }
83592
- function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.1.71" : "" } = {}) {
83583
+ function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.1.73" : "" } = {}) {
83593
83584
  const refused = failures.find((f) => f.error && f.error.code !== "ENOENT");
83594
83585
  const fix = npm ? npmFix(version) : updateCommand({ kind: "native" }, platform2);
83595
83586
  if (!refused) {
@@ -85608,7 +85599,7 @@ var input_default = MultilineInput;
85608
85599
 
85609
85600
  // src/app.jsx
85610
85601
  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
85611
- var MINE = true ? "0.1.71" : "";
85602
+ var MINE = true ? "0.1.73" : "";
85612
85603
  var fmtDur = (s) => s < 60 ? `${Math.max(1, Math.round(s))}s` : `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;
85613
85604
  var plural = (n, w) => `${n} ${w}${n === 1 ? "" : "s"}`;
85614
85605
  var firstResp = (e) => e.first_response_s ? ` \xB7 first response ${e.first_response_s.toFixed(1)}s` : "";
@@ -85732,7 +85723,7 @@ var tallyLine = (tally) => Object.entries(tally).map(([name, t]) => {
85732
85723
  const parts = [t.ok ? `${t.ok} ok` : null, t.failed ? `${t.failed} failed` : null, t.error ? `${t.error} error` : null].filter(Boolean);
85733
85724
  return `${short} ${parts.join(" \xB7 ")}`;
85734
85725
  }).join(" ");
85735
- function App2({ engine: engine2, task, resume, images = [], onUpdate: onUpdate2 = null, peek = peekSession }) {
85726
+ function App2({ engine: engine2, task, resume, images = [], peek = peekSession, update = updateNotice, watch = watchReady }) {
85736
85727
  const { exit } = use_app_default();
85737
85728
  const { stdout } = use_stdout_default();
85738
85729
  const width = (stdout?.columns || 80) - 2;
@@ -85741,6 +85732,7 @@ function App2({ engine: engine2, task, resume, images = [], onUpdate: onUpdate2
85741
85732
  const [status, setStatus] = (0, import_react24.useState)("");
85742
85733
  const [hello, setHello] = (0, import_react24.useState)(null);
85743
85734
  const [latest, setLatest] = (0, import_react24.useState)(null);
85735
+ const [ready, setReady] = (0, import_react24.useState)("");
85744
85736
  const [needYou, setNeedYou] = (0, import_react24.useState)(0);
85745
85737
  const [goal, setGoal] = (0, import_react24.useState)(null);
85746
85738
  const [session, setSession] = (0, import_react24.useState)(null);
@@ -86331,45 +86323,21 @@ function App2({ engine: engine2, task, resume, images = [], onUpdate: onUpdate2
86331
86323
  const t = setInterval(count, NEEDS_EVERY_MS);
86332
86324
  return () => clearInterval(t);
86333
86325
  }, [hello && hello.run_id]);
86334
- const offeredRef = (0, import_react24.useRef)("");
86326
+ const noticedRef = (0, import_react24.useRef)("");
86335
86327
  (0, import_react24.useEffect)(() => {
86336
86328
  if (!latest) return void 0;
86337
- let live = true;
86338
86329
  const mine = MINE || latest.version || "0.0.0";
86339
- updateNotice(mine, { running: latest.version || "", latest: latest.latest_version || "" }).then((line) => {
86340
- if (live && line) append({ kind: "info", text: line });
86341
- }).catch(() => {
86330
+ const want = latest.latest_version || "";
86331
+ const line = update(mine, { running: latest.version || "", latest: want });
86332
+ if (line && noticedRef.current !== line) {
86333
+ noticedRef.current = line;
86334
+ append({ kind: "info", text: line });
86335
+ }
86336
+ return watch(want, (v, already) => {
86337
+ setReady(v);
86338
+ if (!already) append({ kind: "info", text: `hum ${v} is ready \xB7 restart hum to use it` });
86342
86339
  });
86343
- const box = updateBox(mine, latest.latest_version || "", latest.release_notes_url || "");
86344
- if (box && offeredRef.current !== box.latest && updateDue(box.latest)) {
86345
- offeredRef.current = box.latest;
86346
- setPicker((p) => p ? p : { kind: "update", index: 0, box });
86347
- }
86348
- return () => {
86349
- live = false;
86350
- };
86351
86340
  }, [latest]);
86352
- const chooseUpdate = (choice, box) => {
86353
- if (choice === "now") {
86354
- if (!onUpdate2) {
86355
- append({ kind: "info", text: `run ${box.command} to update` });
86356
- return;
86357
- }
86358
- append({ kind: "info", text: `updating hum to ${box.latest} \u2026` });
86359
- onUpdate2(box.latest);
86360
- engine2.send({ cmd: session ? "quit" : "stop" });
86361
- setPhaseBoth("dead");
86362
- setTimeout(() => exit(), 400);
86363
- return;
86364
- }
86365
- if (choice === "skip") {
86366
- skipVersion(box.latest);
86367
- append({ kind: "info", text: `skipping ${box.latest} \xB7 \`hum update\` brings it any time` });
86368
- return;
86369
- }
86370
- const line = laterNotice(box.latest);
86371
- if (line) append({ kind: "info", text: line });
86372
- };
86373
86341
  const quit = () => {
86374
86342
  if (phaseRef.current === "dead") return;
86375
86343
  const busy = phaseRef.current === "busy";
@@ -86568,20 +86536,6 @@ function App2({ engine: engine2, task, resume, images = [], onUpdate: onUpdate2
86568
86536
  else if (input === "s" && !value.trim()) pick(false);
86569
86537
  return;
86570
86538
  }
86571
- if (picker && picker.kind === "update") {
86572
- const n = picker.box.choices.length;
86573
- const choose = (i) => {
86574
- const c = picker.box.choices[i];
86575
- setPicker(null);
86576
- if (c) chooseUpdate(c.key, picker.box);
86577
- };
86578
- if (key.upArrow) setPicker((p) => ({ ...p, index: (p.index + n - 1) % n }));
86579
- else if (key.downArrow || key.tab) setPicker((p) => ({ ...p, index: (p.index + 1) % n }));
86580
- else if (key.escape) choose(1);
86581
- else if (key.return) choose(picker.index);
86582
- else if (/^[1-9]$/.test(input) && Number(input) <= n) choose(Number(input) - 1);
86583
- return;
86584
- }
86585
86539
  if (picker && picker.kind === "model") {
86586
86540
  const it = picker.items[picker.index];
86587
86541
  const pick = () => {
@@ -86840,7 +86794,7 @@ function App2({ engine: engine2, task, resume, images = [], onUpdate: onUpdate2
86840
86794
  setPhaseBoth("busy");
86841
86795
  }
86842
86796
  };
86843
- const statusLine = phase === "connecting" ? "starting \u2026" : `${modelRef.current || ""} \xB7 ${fmtCost2(spend)}` + (ctxPct >= 10 ? ` \xB7 ctx ${ctxPct}%` : "") + (gate === "approve" ? " \xB7 approvals on" : "") + (hello && hello.mounting && hello.mounting.length ? ` \xB7 mounting ${hello.mounting.join(", ")}` : "") + (goal && goal.text ? ` \xB7 \u25CE goal ${goal.status || "active"}` : "") + (needYou ? ` \xB7 ${needYou} need you` : "") + (offer ? " \xB7 /accept \xB7 /reject" : "") + (agents.length && panelIndex < 0 && !looking ? " \xB7 \u2193 agents" : "") + (ctrlc ? " \xB7 ctrl+c again to quit" : " \xB7 / for commands");
86797
+ const statusLine = phase === "connecting" ? "starting \u2026" : `${modelRef.current || ""} \xB7 ${fmtCost2(spend)}` + (ctxPct >= 10 ? ` \xB7 ctx ${ctxPct}%` : "") + (gate === "approve" ? " \xB7 approvals on" : "") + (hello && hello.mounting && hello.mounting.length ? ` \xB7 mounting ${hello.mounting.join(", ")}` : "") + (goal && goal.text ? ` \xB7 \u25CE goal ${goal.status || "active"}` : "") + (needYou ? ` \xB7 ${needYou} need you` : "") + (ready ? ` \xB7 restart for hum ${ready}` : "") + (offer ? " \xB7 /accept \xB7 /reject" : "") + (agents.length && panelIndex < 0 && !looking ? " \xB7 \u2193 agents" : "") + (ctrlc ? " \xB7 ctrl+c again to quit" : " \xB7 / for commands");
86844
86798
  const spinnerLabel = phase === "connecting" ? " starting \u2026" : ` ${status || "working"}${elapsed >= 2 ? ` \xB7 ${fmtDur(elapsed)}` : ""}` + (thinkChars.current > 4e3 ? ` \xB7 ${(thinkChars.current / 1e3).toFixed(0)}k thinking` : "");
86845
86799
  const rows = stdout?.rows || DEFAULT_ROWS;
86846
86800
  const chrome = 1 + 2 + 4 + (value.split("\n").length - 1) + 1 + (menu.length ? menu.length : 0) + (!menu.length && agents.length ? agents.length + 1 : 0) + (looking ? 4 + (looking.question ? (looking.question.options || []).length + 2 : Math.min(PEEK_LINES, looking.lines.length) + 1) : 0) + (question && step ? 6 + stepOptions.length + (questions.length > 1 ? 1 : 0) + (question.summary ? question.summary.split("\n").length : 0) + (question.evidence || []).length : 0) + (proposal ? 4 + proposal.calls.length * (1 + Math.min(DIFF_TAIL_LINES, 8)) : 0) + (reflection ? 8 + reflection.details.split("\n").length : 0) + (confirm ? 4 + Math.min(8, String(confirm.stat || "").split("\n").length) : 0) + (picker ? 14 : 0);
@@ -87156,30 +87110,6 @@ function App2({ engine: engine2, task, resume, images = [], onUpdate: onUpdate2
87156
87110
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "esc goes back" })
87157
87111
  ] })
87158
87112
  ] }),
87159
- picker && picker.kind === "update" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
87160
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
87161
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "yellow", children: "\u2728 " }),
87162
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { bold: true, children: picker.box.head })
87163
- ] }),
87164
- picker.box.notes ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
87165
- "release notes: ",
87166
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { underline: true, children: picker.box.notes })
87167
- ] }) : null,
87168
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: " " }),
87169
- picker.box.choices.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { children: [
87170
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, children: i === picker.index ? "\u276F " : " " }),
87171
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { bold: i === picker.index, children: `${i + 1}. ${c.label}`.padEnd(22) }),
87172
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: i !== picker.index, children: [
87173
- " ",
87174
- c.desc
87175
- ] })
87176
- ] }, c.key)),
87177
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: " " }),
87178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
87179
- "Enter to choose \xB7 Esc to keep going \xB7 by hand: ",
87180
- picker.box.command
87181
- ] })
87182
- ] }),
87183
87113
  picker && picker.kind === "model" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
87184
87114
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: "Select model" }),
87185
87115
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "Switch models. Served via Metaphi AI." }),
@@ -87426,7 +87356,7 @@ init_update();
87426
87356
  init_install();
87427
87357
  var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
87428
87358
  import { spawnSync as spawnSync5 } from "node:child_process";
87429
- var MINE2 = true ? "0.1.71" : "0.0.0";
87359
+ var MINE2 = true ? "0.1.73" : "0.0.0";
87430
87360
  var layout = installLayout();
87431
87361
  function completeInstall() {
87432
87362
  if (layout.kind !== "npm" || !needsInstall(MINE2)) return;
@@ -87468,20 +87398,9 @@ if (ENGINE_COMMANDS.has(argv0[0]) || argv0[0] === "agents" && argv0.includes("--
87468
87398
  }
87469
87399
  process.exit(r.status === null ? 1 : r.status);
87470
87400
  }
87471
- var wantUpdate = "";
87472
- var onUpdate = (version) => {
87473
- wantUpdate = version;
87474
- };
87475
87401
  function leave(engine2) {
87476
87402
  engine2.close();
87477
- if (!wantUpdate) process.exit(0);
87478
- const rc = updateNow(layout);
87479
- if (rc !== 0) {
87480
- process.stderr.write(`the update did not finish \xB7 ${updateCommand(layout)}
87481
- `);
87482
- process.exit(rc);
87483
- }
87484
- process.exit(restart());
87403
+ process.exit(0);
87485
87404
  }
87486
87405
  if (argv0[0] === "agents") {
87487
87406
  const { liveRows: liveRows2 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
@@ -87509,7 +87428,7 @@ if (argv0[0] === "agents") {
87509
87428
  process.stderr.write(exc.message + "\n");
87510
87429
  process.exit(1);
87511
87430
  }
87512
- const app = render_default(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(App2, { engine: engine2, task: null, resume: null, images: [], onUpdate }), { exitOnCtrlC: false });
87431
+ const app = render_default(/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(App2, { engine: engine2, task: null, resume: null, images: [] }), { exitOnCtrlC: false });
87513
87432
  await app.waitUntilExit();
87514
87433
  leave(engine2);
87515
87434
  }
@@ -87562,7 +87481,7 @@ try {
87562
87481
  process.stderr.write(exc.message + "\n");
87563
87482
  process.exit(1);
87564
87483
  }
87565
- 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, onUpdate }), { exitOnCtrlC: false });
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 });
87566
87485
  waitUntilExit().then(() => leave(engine));
87567
87486
  /*! Bundled license information:
87568
87487
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaphi-ai/hum",
3
- "version": "0.1.71",
3
+ "version": "0.1.73",
4
4
  "description": "Hum: a self-improving coding agent for your terminal.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",