@metaphi-ai/hum 0.1.18 → 0.1.20

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 +75 -16
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -83881,7 +83881,7 @@ var tail = (s, n) => {
83881
83881
  var COMMANDS = [
83882
83882
  { name: "/resume", desc: "pick a past session to continue (this machine or any other)" },
83883
83883
  { name: "/compact", desc: "summarise and restart the context now" },
83884
- { name: "/model", desc: "switch the model for this session (/model <name>)" },
83884
+ { name: "/model", desc: "pick the model \u2014 enter makes it the default, s for this session only; /model <name> switches here" },
83885
83885
  { name: "/cost", desc: "tokens and cost so far" },
83886
83886
  { name: "/approve", desc: "approvals on|off \u2014 whether every change and command waits for you first (leaving the sandbox always asks)" },
83887
83887
  { name: "/continue", desc: "after a pause: let the agent carry on" },
@@ -83927,6 +83927,8 @@ function App2({ engine: engine2, task, resume, images = [] }) {
83927
83927
  const turnT0 = (0, import_react24.useRef)(null);
83928
83928
  const thinkT0 = (0, import_react24.useRef)(null);
83929
83929
  const thinkChars = (0, import_react24.useRef)(0);
83930
+ const draftRef = (0, import_react24.useRef)("");
83931
+ const thoughtRef = (0, import_react24.useRef)(null);
83930
83932
  const toolsRef = (0, import_react24.useRef)({});
83931
83933
  const historyRef = (0, import_react24.useRef)(loadHistory());
83932
83934
  const modelRef = (0, import_react24.useRef)("");
@@ -83951,17 +83953,21 @@ function App2({ engine: engine2, task, resume, images = [] }) {
83951
83953
  const foldThinking = () => {
83952
83954
  if (thinkChars.current > 0) {
83953
83955
  const secs = thinkT0.current ? (Date.now() - thinkT0.current) / 1e3 : 0;
83954
- append({ kind: "thought", text: `thought for ${fmtDur(secs)} \xB7 ${(thinkChars.current / 1e3).toFixed(1)}k chars` });
83956
+ thoughtRef.current = { kind: "thought", text: `thought for ${fmtDur(secs)}` };
83955
83957
  }
83956
83958
  setThinking("");
83957
83959
  thinkChars.current = 0;
83958
83960
  thinkT0.current = null;
83959
83961
  };
83960
83962
  const flushDraft = () => {
83961
- setDraft((d) => {
83962
- if (d.trim()) append({ kind: "hum", text: d.trim() });
83963
- return "";
83964
- });
83963
+ const d = draftRef.current.trim();
83964
+ draftRef.current = "";
83965
+ if (d) append({ kind: "hum", text: d });
83966
+ if (thoughtRef.current) {
83967
+ append(thoughtRef.current);
83968
+ thoughtRef.current = null;
83969
+ }
83970
+ setDraft("");
83965
83971
  };
83966
83972
  const handle = (ev) => {
83967
83973
  if (ev.agent) {
@@ -84035,7 +84041,13 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84035
84041
  break;
84036
84042
  }
84037
84043
  case "replay":
84044
+ const ordered = [];
84038
84045
  for (const it of ev.items || []) {
84046
+ const prev = ordered[ordered.length - 1];
84047
+ if (it.type === "text" && prev && prev.type === "thought") ordered.splice(ordered.length - 1, 0, it);
84048
+ else ordered.push(it);
84049
+ }
84050
+ for (const it of ordered) {
84039
84051
  switch (it.type) {
84040
84052
  case "you":
84041
84053
  append({ kind: "you", text: it.text, images: it.images || [] });
@@ -84044,7 +84056,7 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84044
84056
  append({ kind: "hum", text: it.text });
84045
84057
  break;
84046
84058
  case "thought":
84047
- append({ kind: "thought", text: `thought for ${fmtDur(it.secs || 0)} \xB7 ${((it.chars || 0) / 1e3).toFixed(1)}k chars` });
84059
+ append({ kind: "thought", text: `thought for ${fmtDur(it.secs || 0)}` });
84048
84060
  break;
84049
84061
  case "tool_call": {
84050
84062
  toolsRef.current[it.id] = it;
@@ -84110,8 +84122,17 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84110
84122
  append({ kind: "info", text: "no sessions yet" });
84111
84123
  break;
84112
84124
  }
84113
- setPicker({ items: ev.items.slice(0, 12), index: 0 });
84125
+ setPicker({ kind: "session", items: ev.items.slice(0, 12), index: 0 });
84126
+ break;
84127
+ case "models": {
84128
+ if (!ev.items || ev.items.length === 0) {
84129
+ append({ kind: "info", text: "no models to pick from \u2014 sign in (hum login) or bring a key (hum key <provider> <key>)" });
84130
+ break;
84131
+ }
84132
+ const cur = Math.max(0, ev.items.findIndex((m) => m.current));
84133
+ setPicker({ kind: "model", items: ev.items, index: cur, via: ev.via, byo: ev.byo || [] });
84114
84134
  break;
84135
+ }
84115
84136
  case "session":
84116
84137
  setSession(ev.name);
84117
84138
  setSpend(0);
@@ -84136,7 +84157,8 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84136
84157
  setThinking((t) => t + ev.text);
84137
84158
  break;
84138
84159
  case "text_delta":
84139
- if (thinkChars.current > 0 && !draft) foldThinking();
84160
+ if (thinkChars.current > 0) foldThinking();
84161
+ draftRef.current += ev.text;
84140
84162
  setDraft((d) => d + ev.text);
84141
84163
  break;
84142
84164
  case "tool_pending":
@@ -84277,7 +84299,7 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84277
84299
  (0, import_react24.useEffect)(() => {
84278
84300
  if (!hello) return void 0;
84279
84301
  let live = true;
84280
- updateNotice(true ? "0.1.18" : hello.version || "0.0.0").then((line) => {
84302
+ updateNotice(true ? "0.1.20" : hello.version || "0.0.0").then((line) => {
84281
84303
  if (live && line) append({ kind: "info", text: line });
84282
84304
  }).catch(() => {
84283
84305
  });
@@ -84347,13 +84369,25 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84347
84369
  if (picker) {
84348
84370
  if (key.upArrow) setPicker((p) => ({ ...p, index: (p.index + p.items.length - 1) % p.items.length }));
84349
84371
  else if (key.downArrow || key.tab) setPicker((p) => ({ ...p, index: (p.index + 1) % p.items.length }));
84350
- else if (key.return) {
84372
+ else if (key.escape) setPicker(null);
84373
+ else if (picker.kind === "model") {
84374
+ const it = picker.items[picker.index];
84375
+ const pick = (isDefault) => {
84376
+ setPicker(null);
84377
+ if (it.current && !isDefault) return;
84378
+ modelRef.current = it.name;
84379
+ engine2.send({ cmd: "model", name: it.name, default: isDefault });
84380
+ };
84381
+ if (key.return) pick(true);
84382
+ else if (input === "s") pick(false);
84383
+ else if (/^[1-9]$/.test(input) && Number(input) <= picker.items.length) setPicker((p) => ({ ...p, index: Number(input) - 1 }));
84384
+ } else if (key.return) {
84351
84385
  const it = picker.items[picker.index];
84352
84386
  setPicker(null);
84353
84387
  if (it.live && it.live.here) {
84354
84388
  } else if (it.live && it.live.port) attachTo(it.live.port);
84355
84389
  else engine2.send({ cmd: "resume", name: it.name });
84356
- } else if (key.escape) setPicker(null);
84390
+ }
84357
84391
  return;
84358
84392
  }
84359
84393
  if (menu.length > 0) {
@@ -84370,6 +84404,8 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84370
84404
  const attachTo = (port2) => {
84371
84405
  setItems([]);
84372
84406
  setDraft("");
84407
+ draftRef.current = "";
84408
+ thoughtRef.current = null;
84373
84409
  setThinking("");
84374
84410
  thinkChars.current = 0;
84375
84411
  setProposal(null);
@@ -84418,7 +84454,7 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84418
84454
  if (arg) {
84419
84455
  modelRef.current = arg;
84420
84456
  engine2.send({ cmd: "model", name: arg });
84421
- } else append({ kind: "info", text: `model: ${modelRef.current}` });
84457
+ } else engine2.send({ cmd: "model" });
84422
84458
  break;
84423
84459
  case "/cost": {
84424
84460
  const ctx = ctxPct > 0 ? ` \xB7 context ${ctxPct}% of the compaction threshold` : "";
@@ -84502,7 +84538,7 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84502
84538
  setPhaseBoth("busy");
84503
84539
  }
84504
84540
  };
84505
- const statusLine = phase === "connecting" ? "starting the engine \u2026" : `${modelRef.current || ""}${session ? ` \xB7 ${shortSession(session)}` : ""} \xB7 ${fmtCost(spend)}` + (ctxPct >= 10 ? ` \xB7 ctx ${ctxPct}%` : "") + (gate === "approve" ? " \xB7 approvals on" : "") + (ctrlc ? " \xB7 ctrl+c again to quit" : " \xB7 / for commands");
84541
+ const statusLine = phase === "connecting" ? "starting the engine \u2026" : `${modelRef.current || ""} \xB7 ${fmtCost(spend)}` + (ctxPct >= 10 ? ` \xB7 ctx ${ctxPct}%` : "") + (gate === "approve" ? " \xB7 approvals on" : "") + (ctrlc ? " \xB7 ctrl+c again to quit" : " \xB7 / for commands");
84506
84542
  const spinnerLabel = phase === "connecting" ? " starting \u2026" : ` ${status || "working"}${elapsed >= 2 ? ` \xB7 ${fmtDur(elapsed)}` : ""}` + (thinkChars.current > 4e3 ? ` \xB7 ${(thinkChars.current / 1e3).toFixed(0)}k thinking` : "");
84507
84543
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", children: [
84508
84544
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Static, { items, children: (item) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", marginBottom: ["hum", "you", "banner", "turn"].includes(item.kind) ? 1 : 0, children: [
@@ -84689,7 +84725,30 @@ function App2({ engine: engine2, task, resume, images = [] }) {
84689
84725
  c.diff && c.diff.split("\n").length > DIFF_TAIL_LINES ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: ` \u2026 +${c.diff.split("\n").length - DIFF_TAIL_LINES} more diff lines` }) : null
84690
84726
  ] }, c.id))
84691
84727
  ] }),
84692
- picker && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
84728
+ picker && picker.kind === "model" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
84729
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: "Select model" }),
84730
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: `Your pick becomes the default for new sessions.${picker.via ? ` Served via ${picker.via}.` : ""}${picker.byo.length ? ` Your own keys: ${picker.byo.join(", ")} \u2014 /model <provider>/<model> uses one.` : ""}` }),
84731
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: " " }),
84732
+ (() => {
84733
+ const nameW = Math.max(...picker.items.map((m) => m.name.length + (m.current ? 2 : 0)));
84734
+ return picker.items.map((m, i) => {
84735
+ const price = m.price_per_m && m.price_per_m.length === 2 && (m.price_per_m[0] || m.price_per_m[1]) ? `$${m.price_per_m[0]}/$${m.price_per_m[1]} per M` : "";
84736
+ const about = [m.note, price].filter(Boolean).join(" \xB7 ") + (m.default ? (m.note || price ? " \xB7 " : "") + "default" : "");
84737
+ const label = `${i + 1}. ${m.name}${m.current ? " \u2713" : ""}`.padEnd(nameW + 4);
84738
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { children: [
84739
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, children: i === picker.index ? "\u276F " : " " }),
84740
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: m.current ? "green" : void 0, bold: i === picker.index, children: label }),
84741
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: i !== picker.index, children: [
84742
+ " ",
84743
+ about
84744
+ ] })
84745
+ ] }, m.name);
84746
+ });
84747
+ })(),
84748
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: " " }),
84749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "Enter to set as default \xB7 s to use this session only \xB7 Esc to cancel" })
84750
+ ] }),
84751
+ picker && picker.kind === "session" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", paddingX: 1, marginTop: 1, children: [
84693
84752
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
84694
84753
  "pick a session to continue ",
84695
84754
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "\xB7 enter continues \xB7 esc cancels" })
@@ -85017,7 +85076,7 @@ import { spawnSync as spawnSync3 } from "node:child_process";
85017
85076
  var ENGINE_COMMANDS = /* @__PURE__ */ new Set(["run", "login", "logout", "whoami", "model", "key", "sessions", "show", "sync", "skill", "ps", "stop", "hooks", "engine"]);
85018
85077
  var argv0 = process.argv.slice(2);
85019
85078
  if (argv0[0] === "--version" || argv0[0] === "-V") {
85020
- process.stdout.write(`hum ${true ? "0.1.18" : "0.0.0"}
85079
+ process.stdout.write(`hum ${true ? "0.1.20" : "0.0.0"}
85021
85080
  `);
85022
85081
  process.exit(0);
85023
85082
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaphi-ai/hum",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "Hum (हम): a self-improving coding agent for your terminal.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",