@metaphi-ai/hum 0.1.12 → 0.1.14

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 +220 -104
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -22744,10 +22744,10 @@ var require_react_reconciler_development = __commonJS({
22744
22744
  var setErrorHandler = null;
22745
22745
  var setSuspenseHandler = null;
22746
22746
  {
22747
- var copyWithDeleteImpl = function(obj, path4, index2) {
22748
- var key = path4[index2];
22747
+ var copyWithDeleteImpl = function(obj, path5, index2) {
22748
+ var key = path5[index2];
22749
22749
  var updated = isArray(obj) ? obj.slice() : assign({}, obj);
22750
- if (index2 + 1 === path4.length) {
22750
+ if (index2 + 1 === path5.length) {
22751
22751
  if (isArray(updated)) {
22752
22752
  updated.splice(key, 1);
22753
22753
  } else {
@@ -22755,11 +22755,11 @@ var require_react_reconciler_development = __commonJS({
22755
22755
  }
22756
22756
  return updated;
22757
22757
  }
22758
- updated[key] = copyWithDeleteImpl(obj[key], path4, index2 + 1);
22758
+ updated[key] = copyWithDeleteImpl(obj[key], path5, index2 + 1);
22759
22759
  return updated;
22760
22760
  };
22761
- var copyWithDelete = function(obj, path4) {
22762
- return copyWithDeleteImpl(obj, path4, 0);
22761
+ var copyWithDelete = function(obj, path5) {
22762
+ return copyWithDeleteImpl(obj, path5, 0);
22763
22763
  };
22764
22764
  var copyWithRenameImpl = function(obj, oldPath, newPath, index2) {
22765
22765
  var oldKey = oldPath[index2];
@@ -22797,17 +22797,17 @@ var require_react_reconciler_development = __commonJS({
22797
22797
  }
22798
22798
  return copyWithRenameImpl(obj, oldPath, newPath, 0);
22799
22799
  };
22800
- var copyWithSetImpl = function(obj, path4, index2, value) {
22801
- if (index2 >= path4.length) {
22800
+ var copyWithSetImpl = function(obj, path5, index2, value) {
22801
+ if (index2 >= path5.length) {
22802
22802
  return value;
22803
22803
  }
22804
- var key = path4[index2];
22804
+ var key = path5[index2];
22805
22805
  var updated = isArray(obj) ? obj.slice() : assign({}, obj);
22806
- updated[key] = copyWithSetImpl(obj[key], path4, index2 + 1, value);
22806
+ updated[key] = copyWithSetImpl(obj[key], path5, index2 + 1, value);
22807
22807
  return updated;
22808
22808
  };
22809
- var copyWithSet = function(obj, path4, value) {
22810
- return copyWithSetImpl(obj, path4, 0, value);
22809
+ var copyWithSet = function(obj, path5, value) {
22810
+ return copyWithSetImpl(obj, path5, 0, value);
22811
22811
  };
22812
22812
  var findHook = function(fiber, id) {
22813
22813
  var currentHook2 = fiber.memoizedState;
@@ -22817,10 +22817,10 @@ var require_react_reconciler_development = __commonJS({
22817
22817
  }
22818
22818
  return currentHook2;
22819
22819
  };
22820
- overrideHookState = function(fiber, id, path4, value) {
22820
+ overrideHookState = function(fiber, id, path5, value) {
22821
22821
  var hook = findHook(fiber, id);
22822
22822
  if (hook !== null) {
22823
- var newState = copyWithSet(hook.memoizedState, path4, value);
22823
+ var newState = copyWithSet(hook.memoizedState, path5, value);
22824
22824
  hook.memoizedState = newState;
22825
22825
  hook.baseState = newState;
22826
22826
  fiber.memoizedProps = assign({}, fiber.memoizedProps);
@@ -22830,10 +22830,10 @@ var require_react_reconciler_development = __commonJS({
22830
22830
  }
22831
22831
  }
22832
22832
  };
22833
- overrideHookStateDeletePath = function(fiber, id, path4) {
22833
+ overrideHookStateDeletePath = function(fiber, id, path5) {
22834
22834
  var hook = findHook(fiber, id);
22835
22835
  if (hook !== null) {
22836
- var newState = copyWithDelete(hook.memoizedState, path4);
22836
+ var newState = copyWithDelete(hook.memoizedState, path5);
22837
22837
  hook.memoizedState = newState;
22838
22838
  hook.baseState = newState;
22839
22839
  fiber.memoizedProps = assign({}, fiber.memoizedProps);
@@ -22856,8 +22856,8 @@ var require_react_reconciler_development = __commonJS({
22856
22856
  }
22857
22857
  }
22858
22858
  };
22859
- overrideProps = function(fiber, path4, value) {
22860
- fiber.pendingProps = copyWithSet(fiber.memoizedProps, path4, value);
22859
+ overrideProps = function(fiber, path5, value) {
22860
+ fiber.pendingProps = copyWithSet(fiber.memoizedProps, path5, value);
22861
22861
  if (fiber.alternate) {
22862
22862
  fiber.alternate.pendingProps = fiber.pendingProps;
22863
22863
  }
@@ -22866,8 +22866,8 @@ var require_react_reconciler_development = __commonJS({
22866
22866
  scheduleUpdateOnFiber(root, fiber, SyncLane, NoTimestamp);
22867
22867
  }
22868
22868
  };
22869
- overridePropsDeletePath = function(fiber, path4) {
22870
- fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path4);
22869
+ overridePropsDeletePath = function(fiber, path5) {
22870
+ fiber.pendingProps = copyWithDelete(fiber.memoizedProps, path5);
22871
22871
  if (fiber.alternate) {
22872
22872
  fiber.alternate.pendingProps = fiber.pendingProps;
22873
22873
  }
@@ -29136,7 +29136,7 @@ var require_utils = __commonJS({
29136
29136
  state[info.set] = info.to;
29137
29137
  }
29138
29138
  }
29139
- function readState(line) {
29139
+ function readState2(line) {
29140
29140
  let code = codeRegex(true);
29141
29141
  let controlChars = code.exec(line);
29142
29142
  let state = {};
@@ -29336,7 +29336,7 @@ var require_utils = __commonJS({
29336
29336
  let output = [];
29337
29337
  for (let i = 0; i < input.length; i++) {
29338
29338
  let line = rewindState(state, input[i]);
29339
- state = readState(line);
29339
+ state = readState2(line);
29340
29340
  let temp = Object.assign({}, state);
29341
29341
  output.push(unwindState(temp, line));
29342
29342
  }
@@ -29446,7 +29446,7 @@ var require_has_flag = __commonJS({
29446
29446
  var require_supports_colors = __commonJS({
29447
29447
  "node_modules/@colors/colors/lib/system/supports-colors.js"(exports, module) {
29448
29448
  "use strict";
29449
- var os5 = __require("os");
29449
+ var os6 = __require("os");
29450
29450
  var hasFlag2 = require_has_flag();
29451
29451
  var env3 = process.env;
29452
29452
  var forceColor = void 0;
@@ -29484,7 +29484,7 @@ var require_supports_colors = __commonJS({
29484
29484
  }
29485
29485
  var min = forceColor ? 1 : 0;
29486
29486
  if (process.platform === "win32") {
29487
- var osRelease = os5.release().split(".");
29487
+ var osRelease = os6.release().split(".");
29488
29488
  if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
29489
29489
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
29490
29490
  }
@@ -73569,15 +73569,15 @@ var require_route = __commonJS({
73569
73569
  };
73570
73570
  }
73571
73571
  function wrapConversion(toModel, graph) {
73572
- const path4 = [graph[toModel].parent, toModel];
73572
+ const path5 = [graph[toModel].parent, toModel];
73573
73573
  let fn = conversions[graph[toModel].parent][toModel];
73574
73574
  let cur = graph[toModel].parent;
73575
73575
  while (graph[cur].parent) {
73576
- path4.unshift(graph[cur].parent);
73576
+ path5.unshift(graph[cur].parent);
73577
73577
  fn = link3(conversions[graph[cur].parent][cur], fn);
73578
73578
  cur = graph[cur].parent;
73579
73579
  }
73580
- fn.conversion = path4;
73580
+ fn.conversion = path5;
73581
73581
  return fn;
73582
73582
  }
73583
73583
  module.exports = function(fromModel) {
@@ -73817,7 +73817,7 @@ var require_has_flag2 = __commonJS({
73817
73817
  var require_supports_color = __commonJS({
73818
73818
  "node_modules/supports-color/index.js"(exports, module) {
73819
73819
  "use strict";
73820
- var os5 = __require("os");
73820
+ var os6 = __require("os");
73821
73821
  var tty2 = __require("tty");
73822
73822
  var hasFlag2 = require_has_flag2();
73823
73823
  var { env: env3 } = process;
@@ -73865,7 +73865,7 @@ var require_supports_color = __commonJS({
73865
73865
  return min;
73866
73866
  }
73867
73867
  if (process.platform === "win32") {
73868
- const osRelease = os5.release().split(".");
73868
+ const osRelease = os6.release().split(".");
73869
73869
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
73870
73870
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
73871
73871
  }
@@ -80406,8 +80406,8 @@ function Text({ color, backgroundColor, dimColor = false, bold = false, italic =
80406
80406
  }
80407
80407
 
80408
80408
  // node_modules/ink/build/components/ErrorOverview.js
80409
- var cleanupPath = (path4) => {
80410
- return path4?.replace(`file://${cwd()}/`, "");
80409
+ var cleanupPath = (path5) => {
80410
+ return path5?.replace(`file://${cwd()}/`, "");
80411
80411
  };
80412
80412
  var stackUtils = new import_stack_utils.default({
80413
80413
  cwd: cwd(),
@@ -81353,9 +81353,9 @@ var import_react21 = __toESM(require_react(), 1);
81353
81353
 
81354
81354
  // src/app.jsx
81355
81355
  var import_react24 = __toESM(require_react(), 1);
81356
- import fs2 from "node:fs";
81357
- import os3 from "node:os";
81358
- import path from "node:path";
81356
+ import fs3 from "node:fs";
81357
+ import os4 from "node:os";
81358
+ import path2 from "node:path";
81359
81359
 
81360
81360
  // node_modules/ink-spinner/build/index.js
81361
81361
  var import_react22 = __toESM(require_react(), 1);
@@ -83576,13 +83576,45 @@ var WORDMARK = [
83576
83576
  "\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D"
83577
83577
  ];
83578
83578
  var TAGLINE = "\u0939\u092E \xB7 human and model, one harness";
83579
+ var MASCOT = [
83580
+ " \u2584\u2584 \u2584\u2588\u2598",
83581
+ "\u2584\u2584\u259F\u2599\u2588\u2588\u2588\u2599\u2596",
83582
+ " \u2580\u259C\u2588\u259B\u2599\u259A\u2596"
83583
+ ];
83584
+ var MASCOT_WIDTH = 10;
83585
+
83586
+ // src/banner.js
83587
+ function bannerLines(ev, homeRel2 = (p) => p) {
83588
+ const state = ev.state && ev.state !== "new" && ev.state !== "idle" ? ` \xB7 ${ev.state}` : "";
83589
+ const where = `${homeRel2(ev.cwd || "")}${ev.workspace ? ` \xB7 ${ev.workspace}` : ""}`;
83590
+ const agents = ev.agents_model ? ` \xB7 agents on ${ev.agents_model}` : "";
83591
+ return [`hum ${ev.version || ""}`.trim() + state, `${ev.model || ""}${agents}${ev.user ? ` \xB7 ${ev.user}` : ""}`, where];
83592
+ }
83593
+ function mcpLines(ev) {
83594
+ const servers = ev && ev.mcp || [];
83595
+ if (servers.length === 0) {
83596
+ return ["no MCP servers in this session \u2014 add one to ~/.hum/config.toml ([[mcp]] with a name and a url or a command); the ones your deployment provides arrive when you sign in"];
83597
+ }
83598
+ return servers.map((s) => {
83599
+ const at = s.url || s.command || "";
83600
+ if (s.error) return `${s.name} \xB7 ${at} \xB7 not mounted \u2014 ${s.error}`;
83601
+ const n = (s.tools || []).length;
83602
+ return `${s.name} \xB7 ${at} \xB7 ${n} tool${n === 1 ? "" : "s"}${n ? `: ${s.tools.join(", ")}` : ""}`;
83603
+ });
83604
+ }
83579
83605
 
83580
83606
  // src/update.js
83581
- var DIST = "https://storage.googleapis.com/hum-dist";
83582
- async function latestVersion(fetchImpl = globalThis.fetch) {
83583
- if (process.env.HUM_NO_UPDATE_CHECK || typeof fetchImpl !== "function") return "";
83607
+ import fs2 from "node:fs";
83608
+ import os3 from "node:os";
83609
+ import path from "node:path";
83610
+ import { spawn, spawnSync } from "node:child_process";
83611
+ var dist = (env3 = process.env) => (env3.HUM_DIST || "https://storage.googleapis.com/hum-dist").replace(/\/+$/, "");
83612
+ var humHome = (env3 = process.env) => env3.HUM_HOME || path.join(os3.homedir(), ".hum");
83613
+ var win = () => process.platform === "win32";
83614
+ async function latestVersion(fetchImpl = globalThis.fetch, env3 = process.env) {
83615
+ if (env3.HUM_NO_UPDATE_CHECK || typeof fetchImpl !== "function") return "";
83584
83616
  try {
83585
- const r = await fetchImpl(`${DIST}/releases/latest`, { signal: AbortSignal.timeout(2500) });
83617
+ const r = await fetchImpl(`${dist(env3)}/releases/latest`, { signal: AbortSignal.timeout(2500) });
83586
83618
  if (!r.ok) return "";
83587
83619
  const v = (await r.text()).trim();
83588
83620
  return /^\d+\.\d+\.\d+$/.test(v) ? v : "";
@@ -83597,12 +83629,91 @@ var newer = (a, b) => {
83597
83629
  }
83598
83630
  return false;
83599
83631
  };
83600
- var updateCommand = (execPath = process.execPath, platform2 = process.platform) => {
83601
- const native = !/^(node|bun)(\.exe)?$/i.test(String(execPath).split(/[\\/]/).pop());
83602
- if (native) return platform2 === "win32" ? `irm ${DIST}/install.ps1 | iex` : `curl -fsSL ${DIST}/install.sh | sh`;
83632
+ function installLayout(execPath = process.execPath, env3 = process.env) {
83633
+ const exe = String(execPath).split(/[\\/]/).pop();
83634
+ if (/^(node|bun)(\.exe)?$/i.test(exe)) return { kind: env3.HUM_ENGINE_PORT ? "python" : "npm" };
83635
+ let real = execPath;
83636
+ try {
83637
+ real = fs2.realpathSync(execPath);
83638
+ } catch {
83639
+ }
83640
+ return { kind: "native", exe, dir: path.dirname(real), base: path.dirname(path.dirname(real)) };
83641
+ }
83642
+ var updateCommand = (layout = installLayout(), platform2 = process.platform) => {
83643
+ if (layout.kind === "native") return platform2 === "win32" ? `irm ${dist()}/install.ps1 | iex` : `curl -fsSL ${dist()}/install.sh | sh`;
83644
+ if (layout.kind === "python") return "uv tool upgrade hum-cli (or: pip install -U hum-cli)";
83603
83645
  return "npm i -g @metaphi-ai/hum@latest";
83604
83646
  };
83605
- var updateLine = (latest, mine) => latest && newer(latest, mine) ? `hum ${latest} is out (this is ${mine}) \xB7 ${updateCommand()}` : "";
83647
+ var readyVersion = (layout, version) => layout.kind === "native" && version && fs2.existsSync(path.join(layout.base, version, layout.exe)) ? version : "";
83648
+ var stateFile = (env3 = process.env) => path.join(humHome(env3), "update.json");
83649
+ var readState = (env3 = process.env) => {
83650
+ try {
83651
+ return JSON.parse(fs2.readFileSync(stateFile(env3), "utf8"));
83652
+ } catch {
83653
+ return {};
83654
+ }
83655
+ };
83656
+ var writeState = (s, env3 = process.env) => {
83657
+ try {
83658
+ fs2.mkdirSync(humHome(env3), { recursive: true });
83659
+ fs2.writeFileSync(stateFile(env3), JSON.stringify(s));
83660
+ } catch {
83661
+ }
83662
+ };
83663
+ function installerArgv(version, platform2 = process.platform) {
83664
+ const base = dist();
83665
+ if (platform2 === "win32") return ["powershell", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", `irm ${base}/install.ps1 | iex`]];
83666
+ return ["/bin/sh", ["-c", `curl -fsSL "${base}/install.sh" | sh`]];
83667
+ }
83668
+ function startBackgroundUpdate(version, { env: env3 = process.env, now = Date.now(), spawnImpl = spawn } = {}) {
83669
+ if (env3.HUM_NO_AUTO_UPDATE) return false;
83670
+ const s = readState(env3);
83671
+ if (s.version === version && now - (s.started || 0) < 30 * 60 * 1e3) return false;
83672
+ const log = path.join(humHome(env3), "update.log");
83673
+ let out = "ignore";
83674
+ try {
83675
+ fs2.mkdirSync(humHome(env3), { recursive: true });
83676
+ out = fs2.openSync(log, "w");
83677
+ } catch {
83678
+ }
83679
+ const [bin, args2] = installerArgv(version);
83680
+ try {
83681
+ const child = spawnImpl(bin, args2, {
83682
+ detached: true,
83683
+ stdio: ["ignore", out, out],
83684
+ windowsHide: true,
83685
+ env: { ...env3, HUM_VERSION: version, HUM_DIST: dist(env3) }
83686
+ });
83687
+ child.unref();
83688
+ writeState({ version, started: now }, env3);
83689
+ return true;
83690
+ } catch {
83691
+ return false;
83692
+ }
83693
+ }
83694
+ async function updateNotice(mine, { env: env3 = process.env, fetchImpl = globalThis.fetch, layout = installLayout(process.execPath, env3), spawnImpl = spawn } = {}) {
83695
+ const latest = await latestVersion(fetchImpl, env3);
83696
+ if (!latest || !newer(latest, mine)) return "";
83697
+ if (layout.kind !== "native") return `hum ${latest} is out (this is ${mine}) \xB7 ${updateCommand(layout)}`;
83698
+ if (readyVersion(layout, latest)) return `hum ${latest} is ready \xB7 restart hum to use it`;
83699
+ if (startBackgroundUpdate(latest, { env: env3, spawnImpl })) return `hum ${latest} is downloading in the background \xB7 it takes effect the next time you start hum`;
83700
+ const s = readState(env3);
83701
+ if (s.version === latest && !env3.HUM_NO_AUTO_UPDATE) return `hum ${latest} is still installing in the background (${path.join(humHome(env3), "update.log")} has the details)`;
83702
+ return `hum ${latest} is out (this is ${mine}) \xB7 ${updateCommand(layout)}`;
83703
+ }
83704
+ function updateNow(layout = installLayout()) {
83705
+ if (layout.kind === "native") {
83706
+ const [bin, args2] = installerArgv();
83707
+ return spawnSync(bin, args2, { stdio: "inherit", env: { ...process.env, HUM_DIST: dist() } }).status ?? 1;
83708
+ }
83709
+ if (layout.kind === "python") {
83710
+ process.stdout.write(`update with your package manager: ${updateCommand(layout)}
83711
+ `);
83712
+ return 0;
83713
+ }
83714
+ const r = spawnSync(win() ? "npm.cmd" : "npm", ["i", "-g", "@metaphi-ai/hum@latest"], { stdio: "inherit", shell: win() });
83715
+ return r.status ?? 1;
83716
+ }
83606
83717
 
83607
83718
  // src/input.jsx
83608
83719
  var import_react23 = __toESM(require_react(), 1);
@@ -83743,9 +83854,10 @@ var input_default = MultilineInput;
83743
83854
  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
83744
83855
  var fmtDur = (s) => s < 60 ? `${Math.max(1, Math.round(s))}s` : `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;
83745
83856
  var plural = (n, w) => `${n} ${w}${n === 1 ? "" : "s"}`;
83857
+ var firstResp = (e) => e.first_response_s ? ` \xB7 first response ${e.first_response_s.toFixed(1)}s` : "";
83746
83858
  var shortSession = (name) => (name || "").replace(/\.jsonl$/, "");
83747
83859
  var homeRel = (p) => {
83748
- const h = os3.homedir();
83860
+ const h = os4.homedir();
83749
83861
  return p && h && p.startsWith(h) ? "~" + p.slice(h.length) : p;
83750
83862
  };
83751
83863
  var handEdit = (stat) => {
@@ -83756,11 +83868,11 @@ var handEdit = (stat) => {
83756
83868
  ${lines.join("\n ")}`;
83757
83869
  };
83758
83870
  var fmtCost = (c) => c >= 0.01 ? `$${c.toFixed(2)}` : c > 0 ? `$${c.toFixed(4)}` : "$0";
83759
- var HISTORY_PATH = path.join(os3.homedir(), ".hum", "history.json");
83871
+ var HISTORY_PATH = path2.join(os4.homedir(), ".hum", "history.json");
83760
83872
  var HISTORY_MAX = 300;
83761
83873
  var loadHistory = () => {
83762
83874
  try {
83763
- const a = JSON.parse(fs2.readFileSync(HISTORY_PATH, "utf8"));
83875
+ const a = JSON.parse(fs3.readFileSync(HISTORY_PATH, "utf8"));
83764
83876
  return Array.isArray(a) ? a.filter((x) => typeof x === "string") : [];
83765
83877
  } catch {
83766
83878
  return [];
@@ -83768,8 +83880,8 @@ var loadHistory = () => {
83768
83880
  };
83769
83881
  var saveHistory = (arr) => {
83770
83882
  try {
83771
- fs2.mkdirSync(path.dirname(HISTORY_PATH), { recursive: true });
83772
- fs2.writeFileSync(HISTORY_PATH, JSON.stringify(arr.slice(-HISTORY_MAX)));
83883
+ fs3.mkdirSync(path2.dirname(HISTORY_PATH), { recursive: true });
83884
+ fs3.writeFileSync(HISTORY_PATH, JSON.stringify(arr.slice(-HISTORY_MAX)));
83773
83885
  } catch {
83774
83886
  }
83775
83887
  };
@@ -83786,13 +83898,14 @@ var COMMANDS = [
83786
83898
  { name: "/approve", desc: "approvals on|off \u2014 whether every change and command waits for you first (leaving the sandbox always asks)" },
83787
83899
  { name: "/continue", desc: "after a pause: let the agent carry on" },
83788
83900
  { name: "/image", desc: "attach an image file to your next message (/image <path>); ctrl+v pastes a screenshot" },
83789
- { name: "/tools", desc: "what is mounted" },
83901
+ { name: "/mcp", desc: "the MCP servers in this session \u2014 what each mounted, and any that did not" },
83902
+ { name: "/tools", desc: "the tools the model has, and the sandbox they run in" },
83790
83903
  { name: "/hooks", desc: "the lifecycle hooks in scope (~/.hum/hooks.json, <repo>/.hum/hooks.json; Claude Code and Codex hook files too)" },
83791
83904
  { name: "/help", desc: "keys and commands" },
83792
83905
  { name: "/quit", desc: "leave; the session keeps running (hum brings you back)" },
83793
83906
  { name: "/stop", desc: "end this session's engine (the record is saved)" }
83794
83907
  ];
83795
- var HELP = "!cmd runs a command as you \xB7 esc interrupts the model (what it had is kept) \xB7 type while it works to steer \xB7 edit files in your editor any time (recorded as your turn) \xB7 ctrl+o shows the full output of the last tool result \xB7 ctrl+v pastes a screenshot from the clipboard \xB7 @path.png or /image <path> attaches an image file \xB7 commands run in a sandbox (writes in the working directory, no network); leaving it asks you first (enter approves, a typed reason rejects) \xB7 /approve makes every change and command wait for you \xB7 /resume picks a past session (a running one attaches) \xB7 /compact restarts the context from a summary \xB7 ctrl+c twice leaves and the session keeps running (`hum` brings you back) \xB7 /stop ends it";
83908
+ var HELP = "!cmd runs a command as you \xB7 esc interrupts the model (what it had is kept) \xB7 type while it works to steer \xB7 edit files in your editor any time (recorded as your turn) \xB7 ctrl+o shows the full output of the last tool result \xB7 ctrl+v pastes a screenshot from the clipboard \xB7 @path.png or /image <path> attaches an image file \xB7 commands run in a sandbox (writes in the working directory, no network); leaving it asks you first (enter approves, a typed reason rejects) \xB7 /approve makes every change and command wait for you \xB7 /mcp lists the tool servers \xB7 /resume picks a past session (a running one attaches) \xB7 /compact restarts the context from a summary \xB7 ctrl+c twice leaves and the session keeps running (`hum` brings you back) \xB7 /stop ends it";
83796
83909
  var DIFF_TAIL_LINES = 20;
83797
83910
  var OUTPUT_MAX_LINES = 200;
83798
83911
  var ERR_TAIL_LINES = 5;
@@ -83902,13 +84015,8 @@ function App2({ engine: engine2, task, resume, images = [] }) {
83902
84015
  setMeter((m) => ({ ...m, tokens: 0, cap: ev.compact_at || 0 }));
83903
84016
  setGate(ev.gate === "approve" ? "approve" : "off");
83904
84017
  if (ev.session) setSession(ev.session);
83905
- const state = ev.state && ev.state !== "new" && ev.state !== "idle" ? ` \xB7 ${ev.state}` : "";
83906
84018
  if (ev.fresh) append({ kind: "wordmark" });
83907
- append({
83908
- kind: "banner",
83909
- text: `${ev.model}${ev.user ? ` \xB7 ${ev.user}` : ""} \xB7 ${homeRel(ev.cwd)} \xB7 tools: ${ev.tools.join(", ")}${ev.sandbox ? ` \xB7 sandbox: ${ev.sandbox}` : ""}${ev.workspace ? ` \xB7 ${ev.workspace}` : ""}${state}`,
83910
- instruction: ev.session ? ev.instruction : null
83911
- });
84019
+ append({ kind: "banner", lines: bannerLines(ev, homeRel), instruction: ev.session ? ev.instruction : null });
83912
84020
  if (ev.note) append({ kind: "warn", text: ev.note });
83913
84021
  preHello.current.forEach((it) => append(it));
83914
84022
  preHello.current = [];
@@ -83966,7 +84074,7 @@ function App2({ engine: engine2, task, resume, images = [] }) {
83966
84074
  break;
83967
84075
  }
83968
84076
  case "turn_end":
83969
- append({ kind: "turn", text: `${fmtDur(it.elapsed_s || 0)} \xB7 ${plural(it.turns, "step")} \xB7 ${fmtCost(it.cost_usd)} session` });
84077
+ append({ kind: "turn", text: `${fmtDur(it.elapsed_s || 0)} \xB7 ${plural(it.turns, "step")} \xB7 ${fmtCost(it.cost_usd)} session${firstResp(it)}` });
83970
84078
  setSpend(it.cost_usd || 0);
83971
84079
  break;
83972
84080
  case "agent_start":
@@ -84121,7 +84229,7 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84121
84229
  setSpend(ev.cost_usd);
84122
84230
  const dur = turnT0.current ? fmtDur((Date.now() - turnT0.current) / 1e3) : fmtDur(ev.elapsed_s);
84123
84231
  turnT0.current = null;
84124
- append({ kind: "turn", text: `${dur} \xB7 ${plural(ev.turns, "step")} \xB7 ${fmtCost(ev.cost_usd)} session` + (ev.stop_reason !== "done" && !String(ev.stop_reason).startsWith("paused") ? ` \xB7 stopped: ${ev.stop_reason}` : "") });
84232
+ append({ kind: "turn", text: `${dur} \xB7 ${plural(ev.turns, "step")} \xB7 ${fmtCost(ev.cost_usd)} session${firstResp(ev)}` + (ev.stop_reason !== "done" && !String(ev.stop_reason).startsWith("paused") ? ` \xB7 stopped: ${ev.stop_reason}` : "") });
84125
84233
  setPhaseBoth("idle");
84126
84234
  setStatus("");
84127
84235
  break;
@@ -84163,9 +84271,8 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84163
84271
  (0, import_react24.useEffect)(() => {
84164
84272
  if (!hello) return void 0;
84165
84273
  let live = true;
84166
- latestVersion().then((v) => {
84167
- const line = live ? updateLine(v, true ? "0.1.12" : hello.version || "0.0.0") : "";
84168
- if (line) append({ kind: "info", text: line });
84274
+ updateNotice(true ? "0.1.14" : hello.version || "0.0.0").then((line) => {
84275
+ if (live && line) append({ kind: "info", text: line });
84169
84276
  }).catch(() => {
84170
84277
  });
84171
84278
  return () => {
@@ -84312,7 +84419,10 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84312
84419
  else engine2.send({ cmd: "attach", path: arg });
84313
84420
  break;
84314
84421
  case "/tools":
84315
- append({ kind: "info", text: (hello?.tools || []).join(", ") });
84422
+ append({ kind: "info", text: `${(hello?.tools || []).join(", ")} \xB7 sandbox: ${hello?.sandbox || "none"}` });
84423
+ break;
84424
+ case "/mcp":
84425
+ mcpLines(hello).forEach((t) => append({ kind: "info", text: t }));
84316
84426
  break;
84317
84427
  case "/hooks":
84318
84428
  engine2.send({ cmd: "hooks" });
@@ -84378,13 +84488,18 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84378
84488
  WORDMARK.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: row }, i)),
84379
84489
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: TAGLINE })
84380
84490
  ] }),
84381
- item.kind === "banner" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { borderStyle: "round", borderColor: ACCENT, paddingX: 2, flexDirection: "column", alignSelf: "flex-start", children: [
84382
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
84383
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: "\u2733 hum " }),
84384
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "\u0939\u092E" })
84385
- ] }),
84386
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: item.text }),
84387
- item.instruction ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: item.instruction.split("\n")[0].slice(0, width - 8) }) : null
84491
+ item.kind === "banner" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", paddingLeft: 1, children: [
84492
+ MASCOT.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { children: [
84493
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { width: MASCOT_WIDTH + 2, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: row }) }),
84494
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { bold: i === 0, dimColor: i !== 0, children: item.lines[i] || "" })
84495
+ ] }, i)),
84496
+ item.instruction ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { children: [
84497
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { width: MASCOT_WIDTH + 2, flexShrink: 0 }),
84498
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
84499
+ "\u276F ",
84500
+ item.instruction.split("\n")[0].slice(0, width - MASCOT_WIDTH - 6)
84501
+ ] })
84502
+ ] }) : null
84388
84503
  ] }),
84389
84504
  item.kind === "hum" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { children: [
84390
84505
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { width: 2, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, children: "\u25CF" }) }),
@@ -84540,7 +84655,7 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84540
84655
  ] }),
84541
84656
  picker.items.map((it, i) => {
84542
84657
  const live = it.live ? it.live.here ? " \xB7 here" : ` \xB7 ${it.live.state || "running"}` : "";
84543
- const tail2 = (it.steps != null ? ` \xB7 ${plural(it.steps, "step")}` : " \xB7 on the server") + (it.cost_usd ? ` \xB7 ${fmtCost(it.cost_usd)}` : "") + (it.cwd ? ` \xB7 ${path.basename(it.cwd)}` : "") + live;
84658
+ const tail2 = (it.steps != null ? ` \xB7 ${plural(it.steps, "step")}` : " \xB7 on the server") + (it.cost_usd ? ` \xB7 ${fmtCost(it.cost_usd)}` : "") + (it.cwd ? ` \xB7 ${path2.basename(it.cwd)}` : "") + live;
84544
84659
  const room = Math.max(16, width - 13 - tail2.length - 1);
84545
84660
  const what = (it.instruction || "(untitled)").replace(/\s+/g, " ");
84546
84661
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { children: [
@@ -84585,26 +84700,26 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84585
84700
  }
84586
84701
 
84587
84702
  // src/engine.js
84588
- import fs3 from "node:fs";
84703
+ import fs4 from "node:fs";
84589
84704
  import net from "node:net";
84590
- import os4 from "node:os";
84591
- import path2 from "node:path";
84705
+ import os5 from "node:os";
84706
+ import path3 from "node:path";
84592
84707
  import crypto from "node:crypto";
84593
- import { spawn, spawnSync } from "node:child_process";
84594
- var runDir = () => path2.join(process.env.HUM_HOME || path2.join(os4.homedir(), ".hum"), "run");
84708
+ import { spawn as spawn2, spawnSync as spawnSync2 } from "node:child_process";
84709
+ var runDir = () => path3.join(process.env.HUM_HOME || path3.join(os5.homedir(), ".hum"), "run");
84595
84710
  var readRun = (id) => {
84596
84711
  try {
84597
- return JSON.parse(fs3.readFileSync(path2.join(runDir(), `${id}.json`), "utf8"));
84712
+ return JSON.parse(fs4.readFileSync(path3.join(runDir(), `${id}.json`), "utf8"));
84598
84713
  } catch {
84599
84714
  return null;
84600
84715
  }
84601
84716
  };
84602
84717
  var EngineError = class extends Error {
84603
84718
  };
84604
- var win = process.platform === "win32";
84719
+ var win2 = process.platform === "win32";
84605
84720
  var exists = (p) => {
84606
84721
  try {
84607
- fs3.accessSync(p);
84722
+ fs4.accessSync(p);
84608
84723
  return true;
84609
84724
  } catch {
84610
84725
  return false;
@@ -84613,13 +84728,13 @@ var exists = (p) => {
84613
84728
  function uvToolDirs() {
84614
84729
  const dirs = [];
84615
84730
  if (process.env.UV_TOOL_DIR) dirs.push(process.env.UV_TOOL_DIR);
84616
- if (win) {
84617
- for (const base of [process.env.APPDATA, process.env.LOCALAPPDATA]) if (base) dirs.push(path2.join(base, "uv", "tools"));
84618
- } else dirs.push(path2.join(process.env.XDG_DATA_HOME || path2.join(os4.homedir(), ".local", "share"), "uv", "tools"));
84731
+ if (win2) {
84732
+ for (const base of [process.env.APPDATA, process.env.LOCALAPPDATA]) if (base) dirs.push(path3.join(base, "uv", "tools"));
84733
+ } else dirs.push(path3.join(process.env.XDG_DATA_HOME || path3.join(os5.homedir(), ".local", "share"), "uv", "tools"));
84619
84734
  if (!dirs.some(exists)) {
84620
- for (const uv of ["uv", path2.join(os4.homedir(), ".local", "bin", win ? "uv.exe" : "uv")]) {
84735
+ for (const uv of ["uv", path3.join(os5.homedir(), ".local", "bin", win2 ? "uv.exe" : "uv")]) {
84621
84736
  try {
84622
- const r = spawnSync(uv, ["tool", "dir"], { encoding: "utf8", windowsHide: true });
84737
+ const r = spawnSync2(uv, ["tool", "dir"], { encoding: "utf8", windowsHide: true });
84623
84738
  if (r.status === 0 && r.stdout.trim()) {
84624
84739
  dirs.push(r.stdout.trim());
84625
84740
  break;
@@ -84632,7 +84747,7 @@ function uvToolDirs() {
84632
84747
  }
84633
84748
  function enginePython(dirs = uvToolDirs()) {
84634
84749
  for (const dir of dirs) for (const name of ["hum-cli", "hum"]) {
84635
- const py = win ? path2.join(dir, name, "Scripts", "python.exe") : path2.join(dir, name, "bin", "python");
84750
+ const py = win2 ? path3.join(dir, name, "Scripts", "python.exe") : path3.join(dir, name, "bin", "python");
84636
84751
  if (exists(py)) return py;
84637
84752
  }
84638
84753
  return null;
@@ -84640,16 +84755,16 @@ function enginePython(dirs = uvToolDirs()) {
84640
84755
  function siblingEngine(execPath = process.execPath) {
84641
84756
  let dir;
84642
84757
  try {
84643
- dir = path2.dirname(fs3.realpathSync(execPath));
84758
+ dir = path3.dirname(fs4.realpathSync(execPath));
84644
84759
  } catch {
84645
84760
  return null;
84646
84761
  }
84647
- const p = path2.join(dir, "engine", win ? "hum-engine.exe" : "hum-engine");
84762
+ const p = path3.join(dir, "engine", win2 ? "hum-engine.exe" : "hum-engine");
84648
84763
  return exists(p) ? p : null;
84649
84764
  }
84650
84765
  function homeEngine(env3 = process.env) {
84651
- const home = env3.HUM_HOME || path2.join(os4.homedir(), ".hum");
84652
- const py = win ? path2.join(home, "engine", "Scripts", "python.exe") : path2.join(home, "engine", "bin", "python");
84766
+ const home = env3.HUM_HOME || path3.join(os5.homedir(), ".hum");
84767
+ const py = win2 ? path3.join(home, "engine", "Scripts", "python.exe") : path3.join(home, "engine", "bin", "python");
84653
84768
  return exists(py) ? py : null;
84654
84769
  }
84655
84770
  function engineCandidates(env3 = process.env) {
@@ -84665,7 +84780,7 @@ function engineCandidates(env3 = process.env) {
84665
84780
  const py = enginePython();
84666
84781
  if (py) out.push({ bin: py, args: ["-m", "hum.cli", "engine"], where: "the engine's interpreter" });
84667
84782
  out.push({ bin: "hum-engine", args: [], where: "PATH" });
84668
- out.push({ bin: path2.join(os4.homedir(), ".local", "bin", win ? "hum-engine.exe" : "hum-engine"), args: [], where: "uv's bin dir" });
84783
+ out.push({ bin: path3.join(os5.homedir(), ".local", "bin", win2 ? "hum-engine.exe" : "hum-engine"), args: [], where: "uv's bin dir" });
84669
84784
  return out;
84670
84785
  }
84671
84786
  function engineCommand(argv, candidates = engineCandidates()) {
@@ -84684,11 +84799,11 @@ function startFailure(failures) {
84684
84799
  const lines = [
84685
84800
  `Hum's engine is installed (${refused.bin}) but this machine would not start it: ${what}.`
84686
84801
  ];
84687
- if (win) {
84802
+ if (win2) {
84688
84803
  lines.push("On a managed Windows machine that is usually Device Guard / WDAC refusing an executable it does not know.");
84689
84804
  lines.push(`To see the policy's own message, run: "${refused.bin}" --help`);
84690
84805
  const dir = uvToolDirs()[0];
84691
- lines.push(`If uv's environment is elsewhere, point Hum at its interpreter: set HUM_ENGINE=${path2.join(dir || "<uv tool dir>", "hum-cli", "Scripts", "python.exe")} -m hum.cli engine`);
84806
+ 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`);
84692
84807
  } else {
84693
84808
  lines.push('Set HUM_ENGINE to a command that starts it, e.g. HUM_ENGINE="python -m hum.cli engine"');
84694
84809
  }
@@ -84697,9 +84812,9 @@ function startFailure(failures) {
84697
84812
  function attempt({ bin, args: args2 }, cwd2, { task, images, resume }) {
84698
84813
  return new Promise((resolve, reject) => {
84699
84814
  const runId = crypto.randomBytes(6).toString("hex");
84700
- fs3.mkdirSync(runDir(), { recursive: true });
84701
- const logPath = path2.join(runDir(), `${runId}.log`);
84702
- const log = fs3.openSync(logPath, "a");
84815
+ fs4.mkdirSync(runDir(), { recursive: true });
84816
+ const logPath = path3.join(runDir(), `${runId}.log`);
84817
+ const log = fs4.openSync(logPath, "a");
84703
84818
  const argv = [...args2, "-C", cwd2, "--run-id", runId];
84704
84819
  if (task) argv.push("--task", task);
84705
84820
  for (const p of images) argv.push("--image", p);
@@ -84713,13 +84828,13 @@ function attempt({ bin, args: args2 }, cwd2, { task, images, resume }) {
84713
84828
  };
84714
84829
  let child;
84715
84830
  try {
84716
- child = spawn(bin, argv, { stdio: ["ignore", log, log], detached: true, windowsHide: true });
84831
+ child = spawn2(bin, argv, { stdio: ["ignore", log, log], detached: true, windowsHide: true });
84717
84832
  } catch (e) {
84718
- fs3.closeSync(log);
84833
+ fs4.closeSync(log);
84719
84834
  reject({ spawn: e });
84720
84835
  return;
84721
84836
  }
84722
- fs3.closeSync(log);
84837
+ fs4.closeSync(log);
84723
84838
  let died = false;
84724
84839
  child.on("error", (e) => settle(() => reject({ spawn: e })));
84725
84840
  child.on("exit", () => {
@@ -84758,7 +84873,7 @@ function failureMessage(error) {
84758
84873
  function diedMessage(logPath, text = null) {
84759
84874
  let tail2 = "";
84760
84875
  try {
84761
- tail2 = (text ?? fs3.readFileSync(logPath, "utf8")).trim().split("\n").slice(-3).join("\n").trim();
84876
+ tail2 = (text ?? fs4.readFileSync(logPath, "utf8")).trim().split("\n").slice(-3).join("\n").trim();
84762
84877
  } catch {
84763
84878
  }
84764
84879
  return `the engine did not start${tail2 ? `:
@@ -84855,23 +84970,24 @@ var Engine = class {
84855
84970
 
84856
84971
  // src/cli.jsx
84857
84972
  var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
84858
- import fs4 from "node:fs";
84859
- import path3 from "node:path";
84860
- import { spawnSync as spawnSync2 } from "node:child_process";
84973
+ import fs5 from "node:fs";
84974
+ import path4 from "node:path";
84975
+ import { spawnSync as spawnSync3 } from "node:child_process";
84861
84976
  var ENGINE_COMMANDS = /* @__PURE__ */ new Set(["run", "login", "logout", "whoami", "model", "key", "sessions", "show", "sync", "skill", "ps", "stop", "hooks", "engine"]);
84862
84977
  var argv0 = process.argv.slice(2);
84863
84978
  if (argv0[0] === "--version" || argv0[0] === "-V") {
84864
- process.stdout.write(`hum ${true ? "0.1.12" : "0.0.0"}
84979
+ process.stdout.write(`hum ${true ? "0.1.14" : "0.0.0"}
84865
84980
  `);
84866
84981
  process.exit(0);
84867
84982
  }
84983
+ if (argv0[0] === "update") process.exit(updateNow());
84868
84984
  if (ENGINE_COMMANDS.has(argv0[0])) {
84869
84985
  const cmd = engineCommand(argv0);
84870
84986
  if (!cmd) {
84871
84987
  process.stderr.write(startFailure([]) + "\n");
84872
84988
  process.exit(1);
84873
84989
  }
84874
- const r = spawnSync2(cmd.bin, cmd.args, { stdio: "inherit", windowsHide: true });
84990
+ const r = spawnSync3(cmd.bin, cmd.args, { stdio: "inherit", windowsHide: true });
84875
84991
  if (r.error) {
84876
84992
  process.stderr.write(startFailure([{ bin: cmd.bin, error: r.error }]) + "\n");
84877
84993
  process.exit(1);
@@ -84905,10 +85021,10 @@ if (!process.stdin.isTTY) {
84905
85021
  var liveRuns = () => {
84906
85022
  let out = [];
84907
85023
  try {
84908
- for (const f of fs4.readdirSync(runDir())) {
85024
+ for (const f of fs5.readdirSync(runDir())) {
84909
85025
  if (!f.endsWith(".json")) continue;
84910
85026
  try {
84911
- const r = JSON.parse(fs4.readFileSync(path3.join(runDir(), f), "utf8"));
85027
+ const r = JSON.parse(fs5.readFileSync(path4.join(runDir(), f), "utf8"));
84912
85028
  if (r.port && r.session) out.push(r);
84913
85029
  } catch {
84914
85030
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaphi-ai/hum",
3
- "version": "0.1.12",
3
+ "version": "0.1.14",
4
4
  "description": "Hum (हम): a self-improving coding agent for your terminal.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",