@tiens.nguyen/gonext-local-worker 1.0.209 → 1.0.211

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/gonext-repl.mjs +50 -5
  2. package/package.json +1 -1
package/gonext-repl.mjs CHANGED
@@ -175,13 +175,26 @@ function slashCompleter(line) {
175
175
  const hits = COMMAND_NAMES.filter((n) => n.startsWith(line));
176
176
  return [hits.length ? hits : COMMAND_NAMES, line];
177
177
  }
178
- function printCommands() {
179
- console.log(dim(" commands (type / then Tab to complete):"));
180
- for (const c of COMMANDS) {
178
+ function commandRows(prefix = "") {
179
+ const p = (prefix ?? "").trim();
180
+ const show = COMMANDS.filter(
181
+ (c) =>
182
+ !p ||
183
+ p === "/" ||
184
+ [c.name, ...(c.aliases ?? [])].some((n) => n.startsWith(p))
185
+ );
186
+ const list = show.length ? show : COMMANDS;
187
+ const rows = [dim(" commands (Tab completes):")];
188
+ for (const c of list) {
181
189
  const label = c.usage ?? c.name;
182
190
  const alias = c.aliases?.length ? dim(` (${c.aliases.join(", ")})`) : "";
183
- console.log(` ${cyan(label)}${alias}${dim(" — " + c.desc)}`);
191
+ rows.push(` ${cyan(label)}${alias}${dim(" — " + c.desc)}`);
184
192
  }
193
+ return rows;
194
+ }
195
+ // Permanent print (used by /help and a lone-"/" submit — scrolls with history).
196
+ function printCommands(prefix = "") {
197
+ for (const r of commandRows(prefix)) console.log(r);
185
198
  console.log("");
186
199
  }
187
200
 
@@ -214,6 +227,7 @@ const isNetworkError = (e) =>
214
227
  const _lineQueue = [];
215
228
  let _lineWaiter = null;
216
229
  let _stdinClosed = false;
230
+ let slashHintRows = 0; // live slash-command hint rows drawn below the prompt (0 = none)
217
231
  rl.on("line", (l) => {
218
232
  // While a turn is running, IGNORE typed input entirely — no type-ahead, no queued
219
233
  // next question. Only Ctrl+C (handled via SIGINT) does anything mid-turn. Clear the
@@ -223,6 +237,12 @@ rl.on("line", (l) => {
223
237
  rl.cursor = 0;
224
238
  return;
225
239
  }
240
+ // Enter left the cursor on the row where the live slash-hint started — erase it so the
241
+ // command's own output doesn't print over/under a stale hint block.
242
+ if (slashHintRows > 0) {
243
+ process.stdout.write("\x1b[J");
244
+ slashHintRows = 0;
245
+ }
226
246
  const clean = stripAnsiEscapes(l);
227
247
  if (_lineWaiter) {
228
248
  const w = _lineWaiter;
@@ -236,13 +256,38 @@ rl.on("line", (l) => {
236
256
  // turn: echo is already muted, but readline still recalls history into the invisible
237
257
  // buffer on ↑/↓ — reset the line state after every keypress so nothing accumulates or
238
258
  // moves. Ctrl+C is unaffected (readline emits its SIGINT before this handler runs).
259
+ // Live command hint = an EPHEMERAL overlay drawn BELOW the prompt while the line starts
260
+ // with "/", so it redraws as you type (narrowing) and DISAPPEARS when you clear the slash
261
+ // (instead of stacking permanent copies in scrollback). Rendered with relative cursor
262
+ // moves (down to draw, back up to the input line) so it survives terminal scrolling.
263
+ const inputCol = () => 4 + rl.cursor; // ">> " is 3 cols; content starts at col 4 (1-based)
264
+ function clearSlashHint() {
265
+ if (slashHintRows === 0) return;
266
+ // Cursor is on the input line. Drop into the hint region, erase to end of screen, return.
267
+ process.stdout.write("\n\x1b[J" + `\x1b[1A\x1b[${inputCol()}G`);
268
+ slashHintRows = 0;
269
+ }
270
+ function drawSlashHint(line) {
271
+ const rows = commandRows(line);
272
+ // Repaint in place: erase the old block, draw the new one, move the cursor back up.
273
+ const body = rows.map((r) => "\x1b[K" + r).join("\n");
274
+ let out = "";
275
+ if (slashHintRows > 0) out += "\n\x1b[J\x1b[1A"; // wipe previous block, back to input row
276
+ out += "\n" + body; // draw below the input line
277
+ out += `\x1b[${rows.length}A\x1b[${inputCol()}G`; // back up to the input line + column
278
+ process.stdout.write(out);
279
+ slashHintRows = rows.length;
280
+ }
239
281
  if (process.stdin.isTTY) {
240
282
  process.stdin.on("keypress", () => {
241
283
  if (following) {
242
284
  rl.line = "";
243
285
  rl.cursor = 0;
244
286
  rl.historyIndex = -1;
287
+ return;
245
288
  }
289
+ if (rl.line.startsWith("/")) drawSlashHint(rl.line);
290
+ else clearSlashHint();
246
291
  });
247
292
  }
248
293
  rl.on("close", () => {
@@ -947,7 +992,7 @@ async function main() {
947
992
  console.error(red(`gonext: ${err.message}`));
948
993
  process.exit(1);
949
994
  }
950
- console.log(dim("Ask about this repo. Type / (or /help) to list commands Tab completes. Ctrl-C aborts a running turn.\n"));
995
+ console.log(dim("Ask about this repo. Type / to see commands (Tab completes). Ctrl-C aborts a running turn.\n"));
951
996
 
952
997
  const cwd = resolve(process.cwd());
953
998
  const history = await loadSession(cwd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiens.nguyen/gonext-local-worker",
3
- "version": "1.0.209",
3
+ "version": "1.0.211",
4
4
  "description": "Polls GoNext cloud API for async local LLM jobs and runs them against Ollama/OpenAI-compatible servers on this Mac",
5
5
  "type": "module",
6
6
  "license": "MIT",