@metaphi-ai/hum 0.2.17 → 0.2.19

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 +234 -139
  2. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -41083,10 +41083,10 @@ var init_marked_esm = __esm({
41083
41083
  });
41084
41084
  }
41085
41085
  for (const row of rows) {
41086
- item.rows.push(splitCells(row, item.header.length).map((cell) => {
41086
+ item.rows.push(splitCells(row, item.header.length).map((cell2) => {
41087
41087
  return {
41088
- text: cell,
41089
- tokens: this.lexer.inline(cell)
41088
+ text: cell2,
41089
+ tokens: this.lexer.inline(cell2)
41090
41090
  };
41091
41091
  }));
41092
41092
  }
@@ -42082,19 +42082,19 @@ ${content}</tr>
42082
42082
  case "table": {
42083
42083
  const tableToken = token2;
42084
42084
  let header = "";
42085
- let cell = "";
42085
+ let cell2 = "";
42086
42086
  for (let j = 0; j < tableToken.header.length; j++) {
42087
- cell += this.renderer.tablecell(this.parseInline(tableToken.header[j].tokens), { header: true, align: tableToken.align[j] });
42087
+ cell2 += this.renderer.tablecell(this.parseInline(tableToken.header[j].tokens), { header: true, align: tableToken.align[j] });
42088
42088
  }
42089
- header += this.renderer.tablerow(cell);
42089
+ header += this.renderer.tablerow(cell2);
42090
42090
  let body = "";
42091
42091
  for (let j = 0; j < tableToken.rows.length; j++) {
42092
42092
  const row = tableToken.rows[j];
42093
- cell = "";
42093
+ cell2 = "";
42094
42094
  for (let k = 0; k < row.length; k++) {
42095
- cell += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: tableToken.align[k] });
42095
+ cell2 += this.renderer.tablecell(this.parseInline(row[k].tokens), { header: false, align: tableToken.align[k] });
42096
42096
  }
42097
- body += this.renderer.tablerow(cell);
42097
+ body += this.renderer.tablerow(cell2);
42098
42098
  }
42099
42099
  out += this.renderer.table(header, body);
42100
42100
  continue;
@@ -42305,12 +42305,12 @@ ${content}</tr>
42305
42305
  switch (token2.type) {
42306
42306
  case "table": {
42307
42307
  const tableToken = token2;
42308
- for (const cell of tableToken.header) {
42309
- values = values.concat(this.walkTokens(cell.tokens, callback));
42308
+ for (const cell2 of tableToken.header) {
42309
+ values = values.concat(this.walkTokens(cell2.tokens, callback));
42310
42310
  }
42311
42311
  for (const row of tableToken.rows) {
42312
- for (const cell of row) {
42313
- values = values.concat(this.walkTokens(cell.tokens, callback));
42312
+ for (const cell2 of row) {
42313
+ values = values.concat(this.walkTokens(cell2.tokens, callback));
42314
42314
  }
42315
42315
  }
42316
42316
  break;
@@ -44078,17 +44078,17 @@ var require_layout_manager = __commonJS({
44078
44078
  let alloc = {};
44079
44079
  table.forEach(function(row, rowIndex) {
44080
44080
  let col = 0;
44081
- row.forEach(function(cell) {
44082
- cell.y = rowIndex;
44083
- cell.x = rowIndex ? next(alloc, col) : col;
44084
- const rowSpan = cell.rowSpan || 1;
44085
- const colSpan = cell.colSpan || 1;
44081
+ row.forEach(function(cell2) {
44082
+ cell2.y = rowIndex;
44083
+ cell2.x = rowIndex ? next(alloc, col) : col;
44084
+ const rowSpan = cell2.rowSpan || 1;
44085
+ const colSpan = cell2.colSpan || 1;
44086
44086
  if (rowSpan > 1) {
44087
44087
  for (let cs = 0; cs < colSpan; cs++) {
44088
- alloc[cell.x + cs] = rowSpan;
44088
+ alloc[cell2.x + cs] = rowSpan;
44089
44089
  }
44090
44090
  }
44091
- col = cell.x + colSpan;
44091
+ col = cell2.x + colSpan;
44092
44092
  });
44093
44093
  Object.keys(alloc).forEach((idx) => {
44094
44094
  alloc[idx]--;
@@ -44099,8 +44099,8 @@ var require_layout_manager = __commonJS({
44099
44099
  function maxWidth(table) {
44100
44100
  let mw = 0;
44101
44101
  table.forEach(function(row) {
44102
- row.forEach(function(cell) {
44103
- mw = Math.max(mw, cell.x + (cell.colSpan || 1));
44102
+ row.forEach(function(cell2) {
44103
+ mw = Math.max(mw, cell2.x + (cell2.colSpan || 1));
44104
44104
  });
44105
44105
  });
44106
44106
  return mw;
@@ -44123,11 +44123,11 @@ var require_layout_manager = __commonJS({
44123
44123
  }
44124
44124
  function conflictExists(rows, x, y) {
44125
44125
  let i_max = Math.min(rows.length - 1, y);
44126
- let cell = { x, y };
44126
+ let cell2 = { x, y };
44127
44127
  for (let i = 0; i <= i_max; i++) {
44128
44128
  let row = rows[i];
44129
44129
  for (let j = 0; j < row.length; j++) {
44130
- if (cellsConflict(cell, row[j])) {
44130
+ if (cellsConflict(cell2, row[j])) {
44131
44131
  return true;
44132
44132
  }
44133
44133
  }
@@ -44144,12 +44144,12 @@ var require_layout_manager = __commonJS({
44144
44144
  }
44145
44145
  function addRowSpanCells(table) {
44146
44146
  table.forEach(function(row, rowIndex) {
44147
- row.forEach(function(cell) {
44148
- for (let i = 1; i < cell.rowSpan; i++) {
44149
- let rowSpanCell = new RowSpanCell(cell);
44150
- rowSpanCell.x = cell.x;
44151
- rowSpanCell.y = cell.y + i;
44152
- rowSpanCell.colSpan = cell.colSpan;
44147
+ row.forEach(function(cell2) {
44148
+ for (let i = 1; i < cell2.rowSpan; i++) {
44149
+ let rowSpanCell = new RowSpanCell(cell2);
44150
+ rowSpanCell.x = cell2.x;
44151
+ rowSpanCell.y = cell2.y + i;
44152
+ rowSpanCell.colSpan = cell2.colSpan;
44153
44153
  insertCell(rowSpanCell, table[rowIndex + i]);
44154
44154
  }
44155
44155
  });
@@ -44159,22 +44159,22 @@ var require_layout_manager = __commonJS({
44159
44159
  for (let rowIndex = cellRows.length - 1; rowIndex >= 0; rowIndex--) {
44160
44160
  let cellColumns = cellRows[rowIndex];
44161
44161
  for (let columnIndex = 0; columnIndex < cellColumns.length; columnIndex++) {
44162
- let cell = cellColumns[columnIndex];
44163
- for (let k = 1; k < cell.colSpan; k++) {
44162
+ let cell2 = cellColumns[columnIndex];
44163
+ for (let k = 1; k < cell2.colSpan; k++) {
44164
44164
  let colSpanCell = new ColSpanCell();
44165
- colSpanCell.x = cell.x + k;
44166
- colSpanCell.y = cell.y;
44165
+ colSpanCell.x = cell2.x + k;
44166
+ colSpanCell.y = cell2.y;
44167
44167
  cellColumns.splice(columnIndex + 1, 0, colSpanCell);
44168
44168
  }
44169
44169
  }
44170
44170
  }
44171
44171
  }
44172
- function insertCell(cell, row) {
44172
+ function insertCell(cell2, row) {
44173
44173
  let x = 0;
44174
- while (x < row.length && row[x].x < cell.x) {
44174
+ while (x < row.length && row[x].x < cell2.x) {
44175
44175
  x++;
44176
44176
  }
44177
- row.splice(x, 0, cell);
44177
+ row.splice(x, 0, cell2);
44178
44178
  }
44179
44179
  function fillInTable(table) {
44180
44180
  let h_max = maxHeight(table);
@@ -44194,11 +44194,11 @@ var require_layout_manager = __commonJS({
44194
44194
  opts.rowSpan++;
44195
44195
  y2++;
44196
44196
  }
44197
- let cell = new Cell(opts);
44198
- cell.x = opts.x;
44199
- cell.y = opts.y;
44200
- warn(`Missing cell at ${cell.y}-${cell.x}.`);
44201
- insertCell(cell, table[y]);
44197
+ let cell2 = new Cell(opts);
44198
+ cell2.x = opts.x;
44199
+ cell2.y = opts.y;
44200
+ warn(`Missing cell at ${cell2.y}-${cell2.x}.`);
44201
+ insertCell(cell2, table[y]);
44202
44202
  }
44203
44203
  }
44204
44204
  }
@@ -44215,8 +44215,8 @@ var require_layout_manager = __commonJS({
44215
44215
  row = [key, row];
44216
44216
  }
44217
44217
  }
44218
- return row.map(function(cell) {
44219
- return new Cell(cell);
44218
+ return row.map(function(cell2) {
44219
+ return new Cell(cell2);
44220
44220
  });
44221
44221
  });
44222
44222
  }
@@ -44244,11 +44244,11 @@ var require_layout_manager = __commonJS({
44244
44244
  let spanners = [];
44245
44245
  let auto = {};
44246
44246
  table.forEach(function(row) {
44247
- row.forEach(function(cell) {
44248
- if ((cell[colSpan] || 1) > 1) {
44249
- spanners.push(cell);
44247
+ row.forEach(function(cell2) {
44248
+ if ((cell2[colSpan] || 1) > 1) {
44249
+ spanners.push(cell2);
44250
44250
  } else {
44251
- result[cell[x]] = Math.max(result[cell[x]] || 0, cell[desiredWidth] || 0, forcedMin);
44251
+ result[cell2[x]] = Math.max(result[cell2[x]] || 0, cell2[desiredWidth] || 0, forcedMin);
44252
44252
  }
44253
44253
  });
44254
44254
  });
@@ -44258,9 +44258,9 @@ var require_layout_manager = __commonJS({
44258
44258
  }
44259
44259
  });
44260
44260
  for (let k = spanners.length - 1; k >= 0; k--) {
44261
- let cell = spanners[k];
44262
- let span = cell[colSpan];
44263
- let col = cell[x];
44261
+ let cell2 = spanners[k];
44262
+ let span = cell2[colSpan];
44263
+ let col = cell2[x];
44264
44264
  let existingWidth = result[col];
44265
44265
  let editableCols = typeof vals[col] === "number" ? 0 : 1;
44266
44266
  if (typeof existingWidth === "number") {
@@ -44271,16 +44271,16 @@ var require_layout_manager = __commonJS({
44271
44271
  }
44272
44272
  }
44273
44273
  } else {
44274
- existingWidth = desiredWidth === "desiredWidth" ? cell.desiredWidth - 1 : 1;
44274
+ existingWidth = desiredWidth === "desiredWidth" ? cell2.desiredWidth - 1 : 1;
44275
44275
  if (!auto[col] || auto[col] < existingWidth) {
44276
44276
  auto[col] = existingWidth;
44277
44277
  }
44278
44278
  }
44279
- if (cell[desiredWidth] > existingWidth) {
44279
+ if (cell2[desiredWidth] > existingWidth) {
44280
44280
  let i = 0;
44281
- while (editableCols > 0 && cell[desiredWidth] > existingWidth) {
44281
+ while (editableCols > 0 && cell2[desiredWidth] > existingWidth) {
44282
44282
  if (typeof vals[col + i] !== "number") {
44283
- let dif = Math.round((cell[desiredWidth] - existingWidth) / editableCols);
44283
+ let dif = Math.round((cell2[desiredWidth] - existingWidth) / editableCols);
44284
44284
  existingWidth += dif;
44285
44285
  result[col + i] += dif;
44286
44286
  editableCols--;
@@ -44347,15 +44347,15 @@ var require_table = __commonJS({
44347
44347
  }
44348
44348
  let cells = tableLayout.makeTableLayout(array);
44349
44349
  cells.forEach(function(row) {
44350
- row.forEach(function(cell) {
44351
- cell.mergeTableOptions(this.options, cells);
44350
+ row.forEach(function(cell2) {
44351
+ cell2.mergeTableOptions(this.options, cells);
44352
44352
  }, this);
44353
44353
  }, this);
44354
44354
  tableLayout.computeWidths(this.options.colWidths, cells);
44355
44355
  tableLayout.computeHeights(this.options.rowHeights, cells);
44356
44356
  cells.forEach(function(row) {
44357
- row.forEach(function(cell) {
44358
- cell.init(this.options);
44357
+ row.forEach(function(cell2) {
44358
+ cell2.init(this.options);
44359
44359
  }, this);
44360
44360
  }, this);
44361
44361
  let result = [];
@@ -44382,8 +44382,8 @@ var require_table = __commonJS({
44382
44382
  Table2.reset = () => debug.reset();
44383
44383
  function doDraw(row, lineNum, result) {
44384
44384
  let line = [];
44385
- row.forEach(function(cell) {
44386
- line.push(cell.draw(lineNum));
44385
+ row.forEach(function(cell2) {
44386
+ line.push(cell2.draw(lineNum));
44387
44387
  });
44388
44388
  let str = line.join("");
44389
44389
  if (str.length) result.push(str);
@@ -88355,10 +88355,15 @@ function renderBlocks(tokens, width) {
88355
88355
  return parts.filter((p) => p.replace(ANSI_RE, "").trim().length > 0);
88356
88356
  }
88357
88357
  function renderTable(token2, width) {
88358
- const inline2 = (cell) => renderInline(cell.tokens?.length ? cell.tokens : [{ type: "text", text: cell.text }]);
88358
+ const inline2 = (cell2) => renderInline(cell2.tokens?.length ? cell2.tokens : [{ type: "text", text: cell2.text }]);
88359
88359
  const head = token2.header.map((c) => accent(inline2(c)));
88360
88360
  const rows = token2.rows.map((r) => r.map(inline2));
88361
88361
  const ncols = head.length;
88362
+ if (width < ncols * 7 + 1) {
88363
+ return rows.map((row) => row.map(
88364
+ (value, c) => wrapAnsi2(`${head[c]}: ${value}`, width, { hard: true, trim: false })
88365
+ ).join("\n")).join("\n\n");
88366
+ }
88362
88367
  const all = [head, ...rows];
88363
88368
  const natural = head.map((_, c) => Math.max(
88364
88369
  1,
@@ -88385,13 +88390,13 @@ function renderTable(token2, width) {
88385
88390
  over -= 1;
88386
88391
  }
88387
88392
  }
88388
- const fit = (cell, c) => wrapAnsi2(cell || "", content[c], { hard: true, trim: false });
88393
+ const fit = (cell2, c) => wrapAnsi2(cell2 || "", content[c], { hard: true, trim: false });
88389
88394
  const table = new import_cli_table3.default({
88390
88395
  head: head.map(fit),
88391
88396
  colWidths: content.map((w) => w + 2),
88392
88397
  style: { head: [], border: ["grey"], compact: false }
88393
88398
  });
88394
- rows.forEach((r) => table.push(r.map((cell, c) => fit(cell, c))));
88399
+ rows.forEach((r) => table.push(r.map((cell2, c) => fit(cell2, c))));
88395
88400
  return table.toString();
88396
88401
  }
88397
88402
  function renderMarkdown(text, width) {
@@ -88634,7 +88639,7 @@ var win, MINE, npmFix, NPM_FIX, humHome, versionsDir, versionDir, pkgDir, coreDi
88634
88639
  var init_install = __esm({
88635
88640
  "src/install.js"() {
88636
88641
  win = process.platform === "win32";
88637
- MINE = true ? "0.2.17" : "";
88642
+ MINE = true ? "0.2.19" : "";
88638
88643
  npmFix = (version = "") => `npm i -g @metaphi-ai/hum@${version || "latest"} --foreground-scripts`;
88639
88644
  NPM_FIX = npmFix("latest");
88640
88645
  humHome = (env3 = process.env) => env3.HUM_HOME || path.join(os3.homedir(), ".hum");
@@ -88970,10 +88975,10 @@ function clientEnv() {
88970
88975
  platform: process.platform,
88971
88976
  arch: process.arch,
88972
88977
  terminal: process.env.TERM_PROGRAM || (process.env.WT_SESSION ? "Windows Terminal" : process.env.TERM || ""),
88973
- tui: true ? "0.2.17" : ""
88978
+ tui: true ? "0.2.19" : ""
88974
88979
  };
88975
88980
  }
88976
- function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.2.17" : "" } = {}) {
88981
+ function startFailure(failures, { npm = /^(node|bun)(\.exe)?$/i.test(String(process.execPath).split(/[\\/]/).pop()), platform: platform2 = process.platform, version = true ? "0.2.19" : "" } = {}) {
88977
88982
  const refused = failures.find((f) => f.error && f.error.code !== "ENOENT");
88978
88983
  const fix = npm ? npmFix(version) : updateCommand({ kind: "native" }, platform2);
88979
88984
  if (!refused) {
@@ -90237,6 +90242,51 @@ var build_default = Spinner;
90237
90242
  init_wrap_ansi2();
90238
90243
  init_markdown();
90239
90244
 
90245
+ // src/consult.js
90246
+ init_wrap_ansi2();
90247
+ init_markdown();
90248
+ var cell = (s) => String(s || "").replaceAll("\\", "\\\\").replaceAll("|", "\\|").replace(/\r?\n/g, " ");
90249
+ function consultBody(question, step, width, picks = [], cursor = 0) {
90250
+ const parts = [];
90251
+ if (question.kind === "constraints") {
90252
+ const rows = (question.questions || []).filter((q) => q.id !== "missed");
90253
+ if (width >= 60) {
90254
+ parts.push([
90255
+ "| # | Constraint | Source |",
90256
+ "| --- | --- | --- |",
90257
+ ...rows.map((q, i) => `| ${i + 1}. | ${cell(q.question)} | ${cell(q.header)} |`)
90258
+ ].join("\n"));
90259
+ } else {
90260
+ parts.push(rows.map((q, i) => `**${i + 1}. ${q.header || "constraint"}**
90261
+
90262
+ ${q.question}`).join("\n\n"));
90263
+ }
90264
+ } else {
90265
+ if (question.summary) parts.push(question.summary);
90266
+ if (step.header) parts.push(`**${step.header}**`);
90267
+ parts.push(step.question);
90268
+ const options2 = (step.options || []).map((o) => typeof o === "string" ? { label: o } : o);
90269
+ if (question.kind === "decision" && options2.length && width >= 60 && !options2.some((o) => /\n/.test(o.description || ""))) {
90270
+ parts.push([
90271
+ "| # | Choice | Consequences |",
90272
+ "| --- | --- | --- |",
90273
+ ...options2.map((o, i) => `| ${i + 1} | ${cell(o.label)} | ${cell(o.description)} |`)
90274
+ ].join("\n"));
90275
+ } else if (options2.length) {
90276
+ parts.push(options2.map((o, i) => {
90277
+ const mark = step.multi ? `${i === cursor ? "\u203A " : ""}[${picks.includes(o.label) ? "x" : " "}] ` : "";
90278
+ return `${i + 1}. ${mark}${o.label}${step.default === o.label ? " (default)" : ""}${o.description ? ` \u2014 ${o.description}` : ""}`;
90279
+ }).join("\n\n"));
90280
+ }
90281
+ }
90282
+ if (question.evidence?.length) parts.push("**Evidence**\n\n" + question.evidence.join("\n\n"));
90283
+ return wrapAnsi2(
90284
+ renderMarkdown(parts.filter(Boolean).join("\n\n"), width),
90285
+ width,
90286
+ { hard: true, trim: false }
90287
+ ).split("\n");
90288
+ }
90289
+
90240
90290
  // src/wordmark.js
90241
90291
  var WORDMARK = [
90242
90292
  "\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557",
@@ -90356,6 +90406,10 @@ function MultilineInput({
90356
90406
  const { value: value2, cursor: cursor2 } = latest.current;
90357
90407
  const c2 = clamp(cursor2, value2.length);
90358
90408
  if (swallow && swallow(input, key)) return;
90409
+ if (key.return && (key.meta || key.shift)) {
90410
+ insertAt("\n");
90411
+ return;
90412
+ }
90359
90413
  if (key.return) {
90360
90414
  if (Date.now() - burstAt.current < BURST_MS) {
90361
90415
  insertAt("\n");
@@ -90459,7 +90513,7 @@ var input_default = MultilineInput;
90459
90513
 
90460
90514
  // src/app.jsx
90461
90515
  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
90462
- var MINE2 = true ? "0.2.17" : "";
90516
+ var MINE2 = true ? "0.2.19" : "";
90463
90517
  var fmtDur = (s) => s < 60 ? `${Math.max(1, Math.round(s))}s` : `${Math.floor(s / 60)}m ${Math.round(s % 60)}s`;
90464
90518
  var plural = (n, w) => `${n} ${w}${n === 1 ? "" : "s"}`;
90465
90519
  var firstResp = (e) => e.first_response_s ? ` \xB7 first response ${e.first_response_s.toFixed(1)}s` : "";
@@ -90635,6 +90689,9 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
90635
90689
  const [qAnswers, setQAnswers] = (0, import_react36.useState)({});
90636
90690
  const [qPicks, setQPicks] = (0, import_react36.useState)([]);
90637
90691
  const [qCursor, setQCursor] = (0, import_react36.useState)(0);
90692
+ const [consultTop, setConsultTop] = (0, import_react36.useState)(0);
90693
+ const [sendingAsk, setSendingAsk] = (0, import_react36.useState)(null);
90694
+ const pendingAsk = (0, import_react36.useRef)(null);
90638
90695
  const [confirm, setConfirm] = (0, import_react36.useState)(null);
90639
90696
  const [gate, setGate] = (0, import_react36.useState)("off");
90640
90697
  const [paused, setPaused] = (0, import_react36.useState)(false);
@@ -90676,6 +90733,7 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
90676
90733
  setQuestions(next);
90677
90734
  };
90678
90735
  const restartAsk = () => {
90736
+ setConsultTop(0);
90679
90737
  setQStep(0);
90680
90738
  setQAnswers({});
90681
90739
  setQPicks([]);
@@ -90706,7 +90764,15 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
90706
90764
  const step = steps.length ? steps[Math.min(qStep, steps.length - 1)] : null;
90707
90765
  const stepOptions = step ? (step.options || []).map((o) => typeof o === "string" ? { label: o } : o) : [];
90708
90766
  const stepLabels = stepOptions.map((o) => o.label);
90709
- const menu = value.trimStart().startsWith("/") && !value.includes(" ") ? COMMANDS.filter((c) => c.name.startsWith(value.trim())) : [];
90767
+ const listAsk = !!(question && question.kind === "constraints" && question.questions && question.questions.length);
90768
+ const listRows = listAsk ? question.questions.filter((q) => q.id !== "missed") : [];
90769
+ const consultLines = (0, import_react36.useMemo)(
90770
+ () => question && step ? consultBody(question, step, Math.max(20, width - 4), qPicks, qCursor) : [],
90771
+ [question, step, width, qPicks, qCursor]
90772
+ );
90773
+ const consultHeight = Math.max(4, Math.min(18, Math.floor((stdout?.rows || DEFAULT_ROWS) / 2)));
90774
+ const consultStart = Math.min(consultTop, Math.max(0, consultLines.length - consultHeight));
90775
+ const menu = !question && value.trimStart().startsWith("/") && !value.includes(" ") ? COMMANDS.filter((c) => c.name.startsWith(value.trim())) : [];
90710
90776
  const ctxPct = meter.cap > 0 && meter.tokens > 0 ? Math.round(meter.tokens / meter.cap * 100) : 0;
90711
90777
  (0, import_react36.useEffect)(() => {
90712
90778
  if (phase !== "busy" && phase !== "connecting") return void 0;
@@ -90737,6 +90803,8 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
90737
90803
  thinkChars.current = 0;
90738
90804
  setProposal(null);
90739
90805
  setAsks([]);
90806
+ pendingAsk.current = null;
90807
+ setSendingAsk(null);
90740
90808
  restartAsk();
90741
90809
  setPaused(false);
90742
90810
  setPicker(null);
@@ -91059,6 +91127,12 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91059
91127
  addAsk(ev);
91060
91128
  break;
91061
91129
  case "question_closed":
91130
+ if (pendingAsk.current?.id === ev.id) {
91131
+ append({ kind: "you", text: pendingAsk.current.display });
91132
+ pendingAsk.current = null;
91133
+ setSendingAsk(null);
91134
+ setValue("");
91135
+ }
91062
91136
  dropAsk(ev.id);
91063
91137
  append({ kind: "info", text: `answered: ${ev.answer}` });
91064
91138
  break;
@@ -91186,12 +91260,18 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91186
91260
  }
91187
91261
  case "info":
91188
91262
  case "warn": {
91263
+ if (ev.type === "warn" && pendingAsk.current) {
91264
+ pendingAsk.current = null;
91265
+ setSendingAsk(null);
91266
+ }
91189
91267
  const it = { kind: ev.type, text: ev.text };
91190
91268
  if (helloRef.current) append(it);
91191
91269
  else preHello.current.push(it);
91192
91270
  break;
91193
91271
  }
91194
91272
  case "error":
91273
+ pendingAsk.current = null;
91274
+ setSendingAsk(null);
91195
91275
  foldThinking();
91196
91276
  flushDraft();
91197
91277
  if (helloRef.current) append({ kind: "error", text: ev.text });
@@ -91378,43 +91458,47 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91378
91458
  }
91379
91459
  }
91380
91460
  if (question && step && !picker) {
91381
- const n = stepLabels.length;
91382
- if (step.multi && n) {
91383
- if (key.upArrow) {
91384
- setQCursor((c) => (c + n - 1) % n);
91385
- return;
91386
- }
91387
- if (key.downArrow || key.tab) {
91388
- setQCursor((c) => (c + 1) % n);
91389
- return;
91390
- }
91391
- if (input === " " && !value.trim()) {
91392
- togglePick(stepLabels[Math.min(qCursor, n - 1)]);
91393
- return;
91394
- }
91395
- }
91396
- if (!value.trim() && /^[1-9]$/.test(input) && Number(input) <= n) {
91397
- const label = stepLabels[Number(input) - 1];
91398
- if (step.multi) {
91399
- setQCursor(Number(input) - 1);
91400
- togglePick(label);
91401
- } else answerStep(label);
91461
+ if (key.pageDown || key.pageUp) {
91462
+ setConsultTop(Math.max(0, Math.min(
91463
+ consultLines.length - consultHeight,
91464
+ consultStart + (key.pageDown ? consultHeight : -consultHeight)
91465
+ )));
91402
91466
  return;
91403
91467
  }
91404
- if (key.return && !value.trim() || key.escape) {
91405
- if (step.multi && qPicks.length) {
91406
- answerStep(qPicks.join(", "));
91407
- return;
91468
+ if (key.escape || sendingAsk) return;
91469
+ if (!listAsk && question.kind !== "decision") {
91470
+ const n = stepLabels.length;
91471
+ if (step.multi && n) {
91472
+ if (key.upArrow) {
91473
+ setQCursor((c) => (c + n - 1) % n);
91474
+ return;
91475
+ }
91476
+ if (key.downArrow || key.tab) {
91477
+ setQCursor((c) => (c + 1) % n);
91478
+ return;
91479
+ }
91480
+ if (input === " " && !value.trim()) {
91481
+ togglePick(stepLabels[Math.min(qCursor, n - 1)]);
91482
+ return;
91483
+ }
91408
91484
  }
91409
- if (step.default) {
91410
- answerStep("");
91485
+ if (step.multi && !value.trim() && /^[1-9]$/.test(input) && Number(input) <= n) {
91486
+ const label = stepLabels[Number(input) - 1];
91487
+ setQCursor(Number(input) - 1);
91488
+ togglePick(label);
91411
91489
  return;
91412
91490
  }
91413
- if (step.optional) {
91414
- answerStep("");
91491
+ if (key.return && !key.meta && !key.shift && !value.trim()) {
91492
+ if (step.multi && qPicks.length) {
91493
+ answerStep(qPicks.join(", "));
91494
+ return;
91495
+ }
91496
+ if (step.default || step.optional) {
91497
+ answerStep("");
91498
+ return;
91499
+ }
91415
91500
  return;
91416
91501
  }
91417
- return;
91418
91502
  }
91419
91503
  }
91420
91504
  if (picker && picker.kind === "reasoning") {
@@ -91517,20 +91601,43 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91517
91601
  setValue("");
91518
91602
  setQPicks((ps) => ps.includes(label) ? ps.filter((x) => x !== label) : [...ps, label]);
91519
91603
  };
91604
+ const submitAsk = (payload, display) => {
91605
+ if (!question || pendingAsk.current) return;
91606
+ pendingAsk.current = { id: question.id, display };
91607
+ setSendingAsk(question.id);
91608
+ if (core2.send({ cmd: "answer", id: question.id, ...payload }) === false) {
91609
+ pendingAsk.current = null;
91610
+ setSendingAsk(null);
91611
+ append({ kind: "warn", text: "answer not sent \xB7 your draft is kept; reconnect and retry" });
91612
+ }
91613
+ };
91614
+ const holdAll = () => {
91615
+ if (!listAsk) return;
91616
+ const answers = Object.fromEntries(question.questions.map((q) => [q.id, q.id === "missed" ? "" : "holds"]));
91617
+ submitAsk({ answers }, `held all ${listRows.length} as stated`);
91618
+ };
91619
+ const answerWhole = (text) => {
91620
+ if (!text.trim() || /^\d+$/.test(text.trim())) {
91621
+ append({ kind: "warn", text: "say what the number means, or type /hold to confirm every constraint" });
91622
+ return;
91623
+ }
91624
+ submitAsk({ text }, text);
91625
+ };
91520
91626
  const answerStep = (text) => {
91521
91627
  if (!question || !step) return;
91522
- setValue("");
91523
- append({ kind: "you", text: step.secret ? "(kept to yourself)" : text || (step.default ? `(the default: ${step.default})` : "(nothing)") });
91628
+ const display = step.secret ? "(kept to yourself)" : text || (step.default ? `(the default: ${step.default})` : "(nothing)");
91524
91629
  const answers = { ...qAnswers, [step.id]: text };
91525
91630
  if (qStep + 1 < steps.length) {
91631
+ setValue("");
91632
+ append({ kind: "you", text: display });
91526
91633
  setQAnswers(answers);
91527
91634
  setQStep(qStep + 1);
91635
+ setConsultTop(0);
91528
91636
  setQPicks([]);
91529
91637
  setQCursor(0);
91530
91638
  return;
91531
91639
  }
91532
- dropAsk(question.id);
91533
- core2.send({ cmd: "answer", id: question.id, answers });
91640
+ submitAsk({ answers }, display);
91534
91641
  };
91535
91642
  const vote = (polarity, why2 = "") => {
91536
91643
  core2.send({ cmd: polarity > 0 ? "accept" : "reject", ...why2 ? { why: why2 } : {} });
@@ -91661,7 +91768,7 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91661
91768
  const onSubmit = (line) => {
91662
91769
  const raw = line.trim();
91663
91770
  const text = expandPastes(raw);
91664
- setValue("");
91771
+ if (!question) setValue("");
91665
91772
  const queued = attachRef.current;
91666
91773
  const attached = text ? queued.filter((a) => text.includes(a.chip)) : queued;
91667
91774
  const dropped = queued.filter((a) => !attached.includes(a));
@@ -91691,7 +91798,9 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91691
91798
  return;
91692
91799
  }
91693
91800
  if (question && step && !/^\/(quit|exit|stop)\b/.test(raw)) {
91694
- answerStep(text);
91801
+ if (listAsk && text === "/hold") holdAll();
91802
+ else if (listAsk) answerWhole(text);
91803
+ else answerStep(text);
91695
91804
  return;
91696
91805
  }
91697
91806
  if (reflection) closeReflection(reflection.id, "dismiss");
@@ -91721,7 +91830,7 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91721
91830
  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");
91722
91831
  const spinnerLabel = phase === "connecting" ? " starting \u2026" : ` ${status || "working"}${elapsed >= 2 ? ` \xB7 ${fmtDur(elapsed)}` : ""}` + (thinkChars.current > 4e3 ? ` \xB7 ${(thinkChars.current / 1e3).toFixed(0)}k thinking` : "");
91723
91832
  const rows = stdout?.rows || DEFAULT_ROWS;
91724
- 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);
91833
+ 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 ? 9 + Math.min(consultHeight, consultLines.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);
91725
91834
  const liveBudget = Math.max(LIVE_MIN_ROWS, Math.min(DRAFT_TAIL_LINES, rows - 1 - chrome));
91726
91835
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", children: [
91727
91836
  /* @__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: [
@@ -91888,41 +91997,25 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
91888
91997
  ] }),
91889
91998
  question && step && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", borderStyle: "round", borderColor: ACCENT, paddingX: 1, marginTop: 1, children: [
91890
91999
  questions.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: ` 1 of ${questions.length} open asks \xB7 the oldest first` }) : null,
91891
- question.kind && qStep === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
91892
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: question.kind === "decision" ? "\u2726 Review a decision" : question.kind === "constraints" ? "\u2726 Constraints Hum discovered" : "\u2726 Hum asks for your review" }) }),
91893
- question.summary.split("\n").map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: ` ${l}` }, `s${i}`)),
91894
- question.evidence.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: ` evidence: ${e}` }, `e${i}`))
91895
- ] }) : null,
91896
- step.header ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
91897
- " ",
91898
- step.header
91899
- ] }) : null,
91900
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
91901
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: "? " }),
91902
- step.question,
91903
- steps.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: ` (${qStep + 1} of ${steps.length})` }) : null
92000
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: ACCENT, bold: true, children: [
92001
+ listAsk ? `\u2726 Constraints Hum discovered ${listRows.length} \xB7 say what you know about each` : question.kind === "decision" ? "\u2726 Review a decision" : question.kind === "review" ? "\u2726 Hum asks for your review" : "\u2726 Clarification",
92002
+ !listAsk && steps.length > 1 ? ` (${qStep + 1} of ${steps.length})` : ""
91904
92003
  ] }),
91905
- stepOptions.map((o, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { children: [
91906
- step.multi ? i === Math.min(qCursor, stepLabels.length - 1) ? "\u203A " : " " : " ",
91907
- step.multi ? qPicks.includes(o.label) ? "[x] " : "[ ] " : "",
91908
- i + 1,
91909
- ". ",
91910
- o.label,
91911
- o.description ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
91912
- " \u2014 ",
91913
- o.description
91914
- ] }) : null,
91915
- step.default === o.label ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: " (default)" }) : null
91916
- ] }, i)),
91917
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
92004
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { children: consultLines.slice(consultStart, consultStart + consultHeight).join("\n") }),
92005
+ consultLines.length > consultHeight ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: `lines ${consultStart + 1}\u2013${Math.min(consultLines.length, consultStart + consultHeight)} of ${consultLines.length} \xB7 PgUp/PgDn to read` }) : null,
92006
+ listAsk ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "your words are the answer \xB7 add what was missed \xB7 /hold confirms all \xB7 Alt+Enter adds a line \xB7 Esc leaves unanswered" }) : null,
92007
+ question.kind === "review" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "Share solution insights, test inputs and expected results, constraints, or a hypothesis and how to test it." }) : null,
92008
+ question.kind === "decision" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { dimColor: true, children: "Type a choice and your reasoning, or another approach \xB7 Alt+Enter adds a line \xB7 Enter sends" }) : null,
92009
+ sendingAsk === question.id ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, children: "Sending answer\u2026" }) : null,
92010
+ !listAsk ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { dimColor: true, children: [
91918
92011
  " ",
91919
- stepLabels.length ? step.multi ? "a number ticks \xB7 space ticks the one marked \xB7 " : step.graded ? "a number marks \xB7 words after it if you like \xB7 " : "a number picks \xB7 " : "",
91920
- step.graded ? "" : "type an answer",
92012
+ stepLabels.length && question.kind !== "decision" ? step.multi ? "a number ticks \xB7 space ticks the one marked \xB7 " : step.graded ? "a number marks \xB7 words after it if you like \xB7 " : "a number chooses on Enter \xB7 " : "",
92013
+ step.graded ? "" : "type or paste your answer \xB7 Alt+Enter adds a line",
91921
92014
  step.default ? " \xB7 enter takes the default" : "",
91922
92015
  !step.default && step.optional ? " \xB7 enter says nothing" : "",
91923
92016
  step.multi && stepLabels.length ? " \xB7 enter takes what is ticked" : "",
91924
92017
  step.secret ? " \xB7 it is not shown and not recorded" : ""
91925
- ] })
92018
+ ] }) : null
91926
92019
  ] }),
91927
92020
  reflection && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { borderStyle: "round", borderColor: ACCENT, paddingX: 1, marginTop: 1, children: [
91928
92021
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { flexDirection: "column", width: MASCOT_WIDTH + 1, flexShrink: 0, marginRight: 1, children: MASCOT.map((row, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: ACCENT, bold: true, children: row }, i)) }),
@@ -92201,22 +92294,24 @@ function App2({ core: core2, task, resume, images = [], peek = peekSession, upda
92201
92294
  onChange: setValue,
92202
92295
  onSubmit,
92203
92296
  onPaste,
92204
- focus: phase !== "dead",
92297
+ focus: phase !== "dead" && !sendingAsk,
92205
92298
  navActive: menu.length === 0 && panelIndex < 0 && !looking,
92206
92299
  history: historyRef.current,
92207
92300
  mask: !!(step && step.secret),
92208
92301
  swallow: (input, key) => {
92209
92302
  const chunk = !!input && input.length > 1 && !key.ctrl && !key.meta;
92303
+ if (question && (key.pageUp || key.pageDown || sendingAsk)) return true;
92210
92304
  if (picker) return !chunk;
92211
92305
  if (confirm) return !!(key.return || key.escape);
92212
92306
  if (value.trim()) return false;
92213
92307
  if (reflection && why !== reflection.id && (input === "1" || input === "2")) return true;
92214
92308
  if (proposal && (input === "a" || input === "p") && (proposal.remember || []).length) return true;
92215
92309
  if (!question || !step) return false;
92216
- if (/^[1-9]$/.test(input) && Number(input) <= stepLabels.length) return true;
92310
+ if (listAsk || question.kind === "decision") return false;
92311
+ if (step.multi && /^[1-9]$/.test(input) && Number(input) <= stepLabels.length) return true;
92217
92312
  return !!(step.multi && stepLabels.length && input === " ");
92218
92313
  },
92219
- placeholder: why && reflection && why === reflection.id ? "what did it get wrong? (enter alone: just the no)" : question && step ? stepLabels.length ? "a number, or your answer" : "your answer" : proposal ? (proposal.remember || []).length ? "enter approves \xB7 a / p allow this shape \xB7 or type why not" : "enter to approve \xB7 or type why not" : paused ? "paused \xB7 say what to do, or /continue" : phase === "busy" ? "type to steer \xB7 esc to stop \xB7 !cmd runs a command" : session ? "what next?" : "what are we doing?"
92314
+ placeholder: why && reflection && why === reflection.id ? "what did it get wrong? (enter alone: just the no)" : listAsk ? "your words on the list, by number or as one reply" : question && step ? stepLabels.length ? "a number, or your answer" : "your answer" : proposal ? (proposal.remember || []).length ? "enter approves \xB7 a / p allow this shape \xB7 or type why not" : "enter to approve \xB7 or type why not" : paused ? "paused \xB7 say what to do, or /continue" : phase === "busy" ? "type to steer \xB7 esc to stop \xB7 !cmd runs a command" : session ? "what next?" : "what are we doing?"
92220
92315
  }
92221
92316
  )
92222
92317
  ] }),
@@ -92284,7 +92379,7 @@ init_update();
92284
92379
  init_install();
92285
92380
  var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
92286
92381
  import { spawnSync as spawnSync5 } from "node:child_process";
92287
- var MINE3 = true ? "0.2.17" : "0.0.0";
92382
+ var MINE3 = true ? "0.2.19" : "0.0.0";
92288
92383
  var layout = installLayout();
92289
92384
  function completeInstall() {
92290
92385
  if (layout.kind !== "npm" || !needsInstall(MINE3)) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metaphi-ai/hum",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "Hum: a self-improving coding agent for your terminal.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",