@metaphi-ai/hum 0.1.81 → 0.1.83

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 +70 -18
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -83358,33 +83358,41 @@ function packageVersion(entry = process.argv[1]) {
83358
83358
  return "";
83359
83359
  }
83360
83360
  }
83361
- function installerArgv(version, platform2 = process.platform, layout2 = { kind: "native" }) {
83361
+ function installerArgv(version, platform2 = process.platform, layout2 = { kind: "native" }, log = "") {
83362
83362
  const base = dist();
83363
83363
  if (layout2.kind === "npm") {
83364
- return platform2 === "win32" ? ["cmd.exe", ["/d", "/s", "/c", `npm i -g --ignore-scripts @metaphi-ai/hum@${version || "latest"}`]] : ["/bin/sh", ["-c", `npm i -g --ignore-scripts @metaphi-ai/hum@${version || "latest"}`]];
83364
+ const cmd = `npm i -g --ignore-scripts @metaphi-ai/hum@${version || "latest"}`;
83365
+ return platform2 === "win32" ? ["cmd.exe", ["/d", "/s", "/c", `"${cmd}${log ? ` >> "${log}" 2>&1` : ""}"`], { windowsVerbatimArguments: true }] : ["/bin/sh", ["-c", cmd], {}];
83365
83366
  }
83366
- if (platform2 === "win32") return ["powershell", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", `irm ${base}/install.ps1 | iex`]];
83367
- return ["/bin/sh", ["-c", `curl -fsSL "${base}/install.sh" | sh`]];
83367
+ if (platform2 === "win32") {
83368
+ const cmd = `irm ${base}/install.ps1 | iex`;
83369
+ return ["powershell", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", log ? `& { ${cmd} } *>> '${log}'` : cmd], {}];
83370
+ }
83371
+ return ["/bin/sh", ["-c", `curl -fsSL "${base}/install.sh" | sh`], {}];
83368
83372
  }
83369
83373
  function startBackgroundUpdate(version, { env: env3 = process.env, now = Date.now(), spawnImpl = spawn, layout: layout2 = installLayout(process.execPath, env3), platform: platform2 = process.platform } = {}) {
83370
83374
  if (env3.HUM_NO_AUTO_UPDATE || layout2.kind === "python") return false;
83371
83375
  const s = readState(env3);
83372
83376
  if (s.version === version && now - (s.started || 0) < 30 * 60 * 1e3) return false;
83377
+ const hidden = platform2 === "win32";
83373
83378
  const log = path2.join(humHome2(env3), "update.log");
83374
83379
  let out = "ignore";
83380
+ let logged = false;
83375
83381
  try {
83376
83382
  fs3.mkdirSync(humHome2(env3), { recursive: true });
83377
83383
  out = fs3.openSync(log, "w");
83384
+ logged = true;
83385
+ if (hidden) {
83386
+ fs3.closeSync(out);
83387
+ out = "ignore";
83388
+ }
83378
83389
  } catch {
83390
+ out = "ignore";
83379
83391
  }
83380
- const [bin, args2] = installerArgv(version, platform2, layout2);
83392
+ const [bin, args2, extra] = installerArgv(version, platform2, layout2, hidden && logged ? log : "");
83393
+ const io = hidden ? { stdio: "ignore", windowsHide: true } : { detached: true, stdio: ["ignore", out, out], windowsHide: true };
83381
83394
  try {
83382
- const child = spawnImpl(bin, args2, {
83383
- detached: true,
83384
- stdio: ["ignore", out, out],
83385
- windowsHide: true,
83386
- env: { ...env3, HUM_VERSION: version, HUM_DIST: dist(env3) }
83387
- });
83395
+ const child = spawnImpl(bin, args2, { ...io, ...extra, env: { ...env3, HUM_VERSION: version, HUM_DIST: dist(env3) } });
83388
83396
  child.unref();
83389
83397
  writeState({ ...s, version, started: now }, env3);
83390
83398
  return true;
@@ -83400,13 +83408,13 @@ function mismatchLine(mine, running, { env: env3 = process.env, layout: layout2
83400
83408
  if (state && !state.ok && state.wanted === mine && state.error) return `${head}: the update did not finish (${state.error}) \xB7 ${fix}`;
83401
83409
  return `${head} \xB7 ${fix}`;
83402
83410
  }
83403
- function updateNotice(mine, { running = "", latest = "", env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3), spawnImpl = spawn, now = Date.now() } = {}) {
83411
+ function updateNotice(mine, { running = "", latest = "", env: env3 = process.env, layout: layout2 = installLayout(process.execPath, env3), spawnImpl = spawn, now = Date.now(), platform: platform2 = process.platform } = {}) {
83404
83412
  const drift = mismatchLine(mine, running, { env: env3, layout: layout2 });
83405
83413
  if (drift) return drift;
83406
83414
  if (env3.HUM_NO_UPDATE_CHECK || !mine || !latest || !newer(latest, mine)) return "";
83407
83415
  if (env3.HUM_NO_AUTO_UPDATE || layout2.kind === "python") return `hum ${latest} is out \xB7 ${updateCommand(layout2)}`;
83408
83416
  if (readyVersion(layout2, latest)) return `hum ${latest} is ready \xB7 restart hum to use it`;
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`;
83417
+ if (startBackgroundUpdate(latest, { env: env3, spawnImpl, layout: layout2, now, platform: platform2 })) return `hum ${latest} is installing in the background \xB7 it takes effect the next time you start hum`;
83410
83418
  if (readState(env3).version === latest) return `hum ${latest} is still installing in the background (${path2.join(humHome2(env3), "update.log")} has the details)`;
83411
83419
  return "";
83412
83420
  }
@@ -83580,7 +83588,7 @@ function runningVersion(candidates = coreCandidates(), opts = {}) {
83580
83588
  }
83581
83589
  return null;
83582
83590
  }
83583
- function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.1.81" : "" } = {}) {
83591
+ function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.1.83" : "" } = {}) {
83584
83592
  const refused = failures.find((f) => f.error && f.error.code !== "ENOENT");
83585
83593
  const fix = npm ? npmFix(version) : updateCommand({ kind: "native" }, platform2);
83586
83594
  if (!refused) {
@@ -83600,6 +83608,10 @@ function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(proc
83600
83608
  }
83601
83609
  return lines.join("\n");
83602
83610
  }
83611
+ function coreSpawn(argv, logPath, log, platform2 = process.platform) {
83612
+ if (platform2 === "win32") return { argv: [...argv, "--log", logPath], opts: { stdio: "ignore", windowsHide: true } };
83613
+ return { argv, opts: { stdio: ["ignore", log, log], detached: true, windowsHide: true } };
83614
+ }
83603
83615
  function attempt({ bin, args: args2 }, cwd2, { task, images, resume }) {
83604
83616
  return new Promise((resolve, reject) => {
83605
83617
  const runId = crypto.randomBytes(6).toString("hex");
@@ -83619,7 +83631,8 @@ function attempt({ bin, args: args2 }, cwd2, { task, images, resume }) {
83619
83631
  };
83620
83632
  let child;
83621
83633
  try {
83622
- child = spawn2(bin, argv, { stdio: ["ignore", log, log], detached: true, windowsHide: true });
83634
+ const start = coreSpawn(argv, logPath, log);
83635
+ child = spawn2(bin, start.argv, start.opts);
83623
83636
  } catch (e) {
83624
83637
  fs4.closeSync(log);
83625
83638
  reject({ spawn: e });
@@ -85599,7 +85612,7 @@ var input_default = MultilineInput;
85599
85612
 
85600
85613
  // src/app.jsx
85601
85614
  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
85602
- var MINE = true ? "0.1.81" : "";
85615
+ var MINE = true ? "0.1.83" : "";
85603
85616
  var fmtDur = (s) => s < 60 ? `${Math.max(1, Math.round(s))}s` : `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;
85604
85617
  var plural = (n, w) => `${n} ${w}${n === 1 ? "" : "s"}`;
85605
85618
  var firstResp = (e) => e.first_response_s ? ` \xB7 first response ${e.first_response_s.toFixed(1)}s` : "";
@@ -85646,6 +85659,23 @@ var goalLine = (g) => {
85646
85659
  return `goal ${g.status || "active"}: ${g.text}${n ? ` \xB7 ${plural(n, "exchange")}` : ""}`;
85647
85660
  };
85648
85661
  var fmtTokens = (t) => t >= 1e3 ? `${(t / 1e3).toFixed(1)}k tokens` : `${t || 0} tokens`;
85662
+ var fmtN = (n) => n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${(n / 1e3).toFixed(1)}k` : `${n || 0}`;
85663
+ var contextLines = (ev) => {
85664
+ const rows = ev.rows || [];
85665
+ const width = Math.max(12, ...rows.map((r) => r.category.length));
85666
+ const lines = rows.map((r) => `${r.category.padEnd(width)} ${fmtN(r.tokens).padStart(7)} tokens${r.pct != null ? ` ${String(r.pct).padStart(5)}%` : ""}`);
85667
+ const head = ev.window ? `${fmtN(ev.total)} of ${fmtN(ev.window)} tokens \xB7 ${fmtN(ev.free)} free \xB7 compacts at ${fmtN(ev.threshold)}` : `${fmtN(ev.total)} tokens \xB7 compacts at ${fmtN(ev.threshold)}`;
85668
+ return [head, ...lines];
85669
+ };
85670
+ var costLines = (spend, meter, end, ctx = "") => {
85671
+ const lines = [`${fmtCost2(spend)} this session \xB7 ${(meter.input || 0).toLocaleString()}+${(meter.output || 0).toLocaleString()} tokens${ctx}`];
85672
+ if (!end) return lines;
85673
+ if (end.team_cost_usd != null) lines.push(`${fmtCost2(end.team_cost_usd)} with the team \xB7 ${plural(end.team_tasks || 0, "task")} completed by workers`);
85674
+ if (end.exchange_cost_usd != null) lines.push(`last exchange ${fmtCost2(end.exchange_cost_usd)} \xB7 ${fmtN(end.exchange_input_tokens)}+${fmtN(end.exchange_output_tokens)} tokens \xB7 ${fmtDur(end.elapsed_s || 0)} wall \xB7 ${fmtDur(end.model_s || 0)} in the model \xB7 ${fmtDur(end.tool_s || 0)} in tools`);
85675
+ if (end.cache_read_tokens != null) lines.push(`cache ${fmtN(end.cache_read_tokens)} read \xB7 ${fmtN(end.cache_write_tokens)} written \xB7 ${fmtN(end.reasoning_tokens)} reasoning`);
85676
+ for (const [m, u] of Object.entries(end.by_model || {})) lines.push(`${m} \xB7 ${plural(u.calls || 0, "call")} \xB7 ${fmtN(u.input_tokens)}+${fmtN(u.output_tokens)} tokens \xB7 ${fmtN(u.cache_read_tokens)} cached \xB7 ${fmtCost2(u.cost_usd || 0)}`);
85677
+ return lines;
85678
+ };
85649
85679
  var HISTORY_PATH = path5.join(os6.homedir(), ".hum", "history.json");
85650
85680
  var HISTORY_MAX = 300;
85651
85681
  var loadHistory = () => {
@@ -85680,12 +85710,14 @@ var COMMANDS = [
85680
85710
  { name: "/accept", desc: "the work as it stands is what you wanted (/accept <why>); recorded against the state it is in" },
85681
85711
  { name: "/reject", desc: "the work as it stands is not (/reject <why>)" },
85682
85712
  { name: "/cost", desc: "tokens and cost so far" },
85713
+ { name: "/context", desc: "what fills the context window: system prompt, tool schemas, messages, tool results" },
85683
85714
  { name: "/usage-credits", desc: "your credits on our models, and the page that adds more (a code from Metaphi, or a purchase)" },
85684
85715
  { name: "/approve", desc: "approvals on|off \u2014 whether every change and command waits for you first (leaving the sandbox always asks)" },
85685
85716
  { name: "/continue", desc: "after a pause: let the agent carry on" },
85686
85717
  { 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
85718
  { name: "/image", desc: "attach an image file to your next message (/image <path>); ctrl+v pastes a screenshot" },
85688
85719
  { name: "/mcp", desc: "the MCP servers in this session \u2014 what each mounted, and any that did not" },
85720
+ { name: "/memory", desc: "what this project taught Humboldt: where the memory files are and one line per entry; edit the files by hand" },
85689
85721
  { 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
85722
  { name: "/tools", desc: "the tools the model has, and the sandbox they run in" },
85691
85723
  { name: "/hooks", desc: "the lifecycle hooks in scope (~/.hum/hooks.json, <repo>/.hum/hooks.json; Claude Code and Codex hook files too)" },
@@ -85784,6 +85816,7 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
85784
85816
  const wroteRef = (0, import_react24.useRef)(false);
85785
85817
  const preHello = (0, import_react24.useRef)([]);
85786
85818
  const [meter, setMeter] = (0, import_react24.useState)({ tokens: 0, cap: 0, input: 0, output: 0 });
85819
+ const lastEnd = (0, import_react24.useRef)(null);
85787
85820
  const setPhaseBoth = (p) => {
85788
85821
  phaseRef.current = p;
85789
85822
  setPhase(p);
@@ -86037,6 +86070,7 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
86037
86070
  case "turn_end":
86038
86071
  append({ kind: "turn", text: `${fmtDur(it.elapsed_s || 0)} \xB7 ${plural(it.turns, "step")} \xB7 ${fmtCost2(it.cost_usd)} session${firstResp(it)}` });
86039
86072
  setSpend(it.cost_usd || 0);
86073
+ lastEnd.current = it;
86040
86074
  break;
86041
86075
  case "agent_start":
86042
86076
  append({ kind: "agent", text: `agent ${it.n} \xB7 ${it.kind} \xB7 ${it.desc}` });
@@ -86181,6 +86215,13 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
86181
86215
  case "mcp":
86182
86216
  append({ kind: "mcp", servers: ev.servers || [] });
86183
86217
  break;
86218
+ case "memory": {
86219
+ const items2 = ev.items || [];
86220
+ append({ kind: "info", text: `memory: ${ev.dir}${items2.some((i) => i.source === "repo") ? ` \xB7 shared: ${ev.repo_dir}` : ""}` });
86221
+ if (!items2.length) append({ kind: "info", text: "nothing remembered yet; the model writes here with remember, and you may edit the files by hand" });
86222
+ for (const it of items2) append({ kind: "info", text: ` ${it.name} (${it.type}${it.source === "repo" ? ", shared" : ""}): ${it.description}` });
86223
+ break;
86224
+ }
86184
86225
  case "reflection":
86185
86226
  setReflections((rs) => rs.some((r) => r.id === ev.id) ? rs : [...rs, { id: ev.id, category: ev.category || "other", title: ev.title || "", details: ev.details || "", area: ev.area || "" }]);
86186
86227
  break;
@@ -86207,6 +86248,9 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
86207
86248
  setProposal(null);
86208
86249
  append({ kind: "info", text: "approvals off: the waiting proposal ran" });
86209
86250
  break;
86251
+ case "context":
86252
+ append({ kind: "info", text: contextLines(ev).join("\n") });
86253
+ break;
86210
86254
  case "diff": {
86211
86255
  const text = String(ev.text || "");
86212
86256
  if (!text.trim()) {
@@ -86273,6 +86317,7 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
86273
86317
  if (ev.tally && Object.keys(ev.tally).length) append({ kind: "tally", text: tallyLine(ev.tally) });
86274
86318
  setMeter((m) => ({ ...m, tokens: ev.context_tokens ?? m.tokens, input: ev.input_tokens || 0, output: ev.output_tokens || 0 }));
86275
86319
  setSpend(ev.cost_usd);
86320
+ lastEnd.current = ev;
86276
86321
  const dur = turnT0.current ? fmtDur((Date.now() - turnT0.current) / 1e3) : fmtDur(ev.elapsed_s);
86277
86322
  turnT0.current = null;
86278
86323
  append({ kind: "turn", text: `${dur} \xB7 ${plural(ev.turns, "step")} \xB7 ${fmtCost2(ev.cost_usd)} session${firstResp(ev)}` + (ev.stop_reason !== "done" && !String(ev.stop_reason).startsWith("paused") ? ` \xB7 stopped: ${ev.stop_reason}` : "") });
@@ -86678,13 +86723,16 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
86678
86723
  case "/diff":
86679
86724
  core2.send({ cmd: "diff", scope: arg });
86680
86725
  break;
86726
+ case "/context":
86727
+ core2.send({ cmd: "context" });
86728
+ break;
86681
86729
  case "/rewind":
86682
86730
  wantRow.current = /^\d+$/.test(arg) ? Number(arg) : null;
86683
86731
  core2.send({ cmd: "rewind_list" });
86684
86732
  break;
86685
86733
  case "/cost": {
86686
86734
  const ctx = ctxPct > 0 ? ` \xB7 context ${ctxPct}% of the compaction threshold` : "";
86687
- append({ kind: "info", text: `${fmtCost2(spend)} this session \xB7 ${meter.input.toLocaleString()}+${meter.output.toLocaleString()} tokens${ctx}` });
86735
+ append({ kind: "info", text: costLines(spend, meter, lastEnd.current, ctx).join("\n") });
86688
86736
  break;
86689
86737
  }
86690
86738
  case "/image":
@@ -86709,6 +86757,10 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
86709
86757
  core2.send({ cmd: "slack" });
86710
86758
  break;
86711
86759
  // the core's words: the session's Slack surface
86760
+ case "/memory":
86761
+ core2.send({ cmd: "memory" });
86762
+ break;
86763
+ // the core's data: the project's memory
86712
86764
  case "/hooks":
86713
86765
  core2.send({ cmd: "hooks" });
86714
86766
  break;
@@ -87356,7 +87408,7 @@ init_update();
87356
87408
  init_install();
87357
87409
  var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
87358
87410
  import { spawnSync as spawnSync5 } from "node:child_process";
87359
- var MINE2 = true ? "0.1.81" : "0.0.0";
87411
+ var MINE2 = true ? "0.1.83" : "0.0.0";
87360
87412
  var layout = installLayout();
87361
87413
  function completeInstall() {
87362
87414
  if (layout.kind !== "npm" || !needsInstall(MINE2)) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaphi-ai/hum",
3
- "version": "0.1.81",
3
+ "version": "0.1.83",
4
4
  "description": "Hum: a self-improving coding agent for your terminal.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",