@tiens.nguyen/gonext-cli 1.0.367 → 1.0.368
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.
- package/gonext-repl.mjs +39 -8
- package/package.json +1 -1
package/gonext-repl.mjs
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* interrupted investigation actually resumes it). /reset clears it.
|
|
22
22
|
*
|
|
23
23
|
* Requires the worker daemon to be running (it claims the job).
|
|
24
|
-
* Commands: /exit /model /reset /
|
|
24
|
+
* Commands: /exit /model /reset /manual-edit [runId] /help Ctrl-C stops following the current run.
|
|
25
25
|
*/
|
|
26
26
|
import { readFile, mkdir, writeFile, unlink } from "node:fs/promises";
|
|
27
27
|
import { existsSync, statSync, readFileSync } from "node:fs";
|
|
@@ -286,7 +286,7 @@ if (argv.includes("--help") || argv.includes("-h")) {
|
|
|
286
286
|
" -v, --verbose show the agent's diagnostic logs ([gonext-agent] …) and python stderr\n" +
|
|
287
287
|
" -h, --help this help\n\n" +
|
|
288
288
|
"Auth comes from ~/.gonext/worker.env; models/budgets/RAG come from your web Settings.\n" +
|
|
289
|
-
"Inside the REPL: /exit · /model · /reset · /
|
|
289
|
+
"Inside the REPL: /exit · /model · /reset · /manual-edit [runId] · /help — Ctrl-C stops following a turn.\n" +
|
|
290
290
|
"Questions are enqueued like web questions and executed by the RUNNING\n" +
|
|
291
291
|
"gonext-cli daemon — its terminal shows the full [gonext-agent] logs.\n" +
|
|
292
292
|
"Conversation history is saved per-folder in ~/.gonext/sessions and resumed next time\n" +
|
|
@@ -360,7 +360,7 @@ const COMMANDS = [
|
|
|
360
360
|
{ name: "/test-auto", desc: "toggle auto-test (verify & fix until it passes) for this folder" },
|
|
361
361
|
{ name: "/rag-local", desc: "toggle storing this folder's RAG knowledge base locally (vs cloud/S3)" },
|
|
362
362
|
{ name: "/server", desc: "pick a deployment server (host/user) for this session" },
|
|
363
|
-
{ name: "/revert", usage: "/
|
|
363
|
+
{ name: "/manual-edit", aliases: ["/revert"], usage: "/manual-edit [runId]", desc: "undo the agent's file edits so you can edit them yourself (latest run)" },
|
|
364
364
|
{ name: "/reset", aliases: ["/new"], desc: "forget this folder's saved conversation and start fresh" },
|
|
365
365
|
{ name: "/output-token", desc: "show the agent code-model OUTPUT-token total for this workspace" },
|
|
366
366
|
{ name: "/reset-output-token-global", desc: "reset the GLOBAL (you + coding server) output-token total to 0" },
|
|
@@ -641,6 +641,26 @@ if (process.stdout.isTTY) {
|
|
|
641
641
|
}
|
|
642
642
|
});
|
|
643
643
|
}
|
|
644
|
+
// ---------- edit-mode bottom bar (display-only + Shift+Tab to cycle) ----------
|
|
645
|
+
// A split line + a mode indicator shown just above the prompt each turn: "accept edits on"
|
|
646
|
+
// (the agent applies file edits — today's behaviour) vs "manually edit". DISPLAY-ONLY for now
|
|
647
|
+
// — it tracks the mode so the bar reflects it and Shift+Tab cycles it; wiring it to actually
|
|
648
|
+
// gate the agent's edits is a deliberate follow-up.
|
|
649
|
+
let editMode = "accept"; // "accept" | "manual"
|
|
650
|
+
const modeLineText = () =>
|
|
651
|
+
white("✎ " + (editMode === "accept" ? "accept edits on" : "manually edit")) +
|
|
652
|
+
dim(" (shift+tab to switch)");
|
|
653
|
+
// The bar: a full-width dim rule (turn separator), then the gutter-inset mode line. Printed
|
|
654
|
+
// above the prompt in the main loop.
|
|
655
|
+
const modeBar = () =>
|
|
656
|
+
dim("─".repeat(process.stdout.columns || 80)) + "\n" + GUTTER + modeLineText();
|
|
657
|
+
// Shift+Tab redraw: the mode line sits ONE physical row above the ">> " input line. Move up,
|
|
658
|
+
// rewrite it, drop back, and let readline restore the input row + caret (cursor-relative, like
|
|
659
|
+
// the status ticker / pickers, so it survives scrolling).
|
|
660
|
+
const redrawModeLine = () => {
|
|
661
|
+
process.stdout.write("\x1b[1A\r\x1b[2K" + GUTTER + modeLineText() + "\x1b[1B\r");
|
|
662
|
+
rl._refreshLine();
|
|
663
|
+
};
|
|
644
664
|
if (process.stdin.isTTY) {
|
|
645
665
|
process.stdin.on("keypress", (_ch, key) => {
|
|
646
666
|
// An arrow-key list picker (/server) is up → ↑/↓ move the highlight, Enter chooses.
|
|
@@ -665,6 +685,15 @@ if (process.stdin.isTTY) {
|
|
|
665
685
|
rl.historyIndex = -1;
|
|
666
686
|
return;
|
|
667
687
|
}
|
|
688
|
+
// Shift+Tab cycles the edit mode shown in the bottom bar (display-only). Skip while the
|
|
689
|
+
// slash overlay owns the screen so we don't fight its redraw.
|
|
690
|
+
if (key && key.name === "tab" && key.shift) {
|
|
691
|
+
if (!slashOverlayActive) {
|
|
692
|
+
editMode = editMode === "accept" ? "manual" : "accept";
|
|
693
|
+
redrawModeLine();
|
|
694
|
+
}
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
668
697
|
// Enter is handled by rl.on("line") — don't redraw the hint on the way out.
|
|
669
698
|
if (key && (key.name === "return" || key.name === "enter")) return;
|
|
670
699
|
// ↑/↓ while the menu is up = move the highlight IN PLACE. readline drawing is
|
|
@@ -2525,14 +2554,13 @@ async function main() {
|
|
|
2525
2554
|
bold(cyan("GONEXT AGENT")) + dim(` v${REPL_VERSION}`),
|
|
2526
2555
|
lbl("model") + (p.agentModelId || probe?.modelKey || "?"),
|
|
2527
2556
|
lbl("coder") + (p.codingModelId || dim("—")),
|
|
2528
|
-
lbl("RAG") +
|
|
2529
|
-
|
|
2530
|
-
dim(" auto-test ") + (sessionTestAuto ? "on" : dim("off")),
|
|
2557
|
+
lbl("RAG") + (p.ragEnabled ? (sessionRagMode === "cloud" ? "cloud" : "local") : dim("off")),
|
|
2558
|
+
sessionTestAuto ? green("auto-test on") : dim("auto-test off"),
|
|
2531
2559
|
lbl("folder") + ws + dim(wsSync ? ` (${wsSync.run ? "run" : "read-only"}${wsSync.enabled ? " · sync" : ""})` : ""),
|
|
2532
2560
|
];
|
|
2533
2561
|
if (selectedServer)
|
|
2534
2562
|
statusRows.push(lbl("deploy") + `${selectedServer.name} ${dim(`(${selectedServer.user}@${selectedServer.host})`)}`);
|
|
2535
|
-
statusRows.push(dim(`
|
|
2563
|
+
statusRows.push(dim(`key ${workerKey.slice(0, 8)}…`));
|
|
2536
2564
|
console.log(renderBanner(statusRows));
|
|
2537
2565
|
}
|
|
2538
2566
|
// Task #127, Phase 3: if the base chat model server isn't answering, offer to set it up
|
|
@@ -2655,6 +2683,9 @@ async function main() {
|
|
|
2655
2683
|
let lastCancelledTask = "";
|
|
2656
2684
|
|
|
2657
2685
|
for (;;) {
|
|
2686
|
+
// The bottom bar (split line + edit-mode indicator) sits just above the prompt each turn;
|
|
2687
|
+
// the mode line is exactly ONE row above ">> " so Shift+Tab can redraw it in place.
|
|
2688
|
+
if (process.stdout.isTTY) process.stdout.write(modeBar() + "\n");
|
|
2658
2689
|
rl.prompt();
|
|
2659
2690
|
// Absorb blank Enter-presses SILENTLY under the same prompt — without this, lines
|
|
2660
2691
|
// typed while the agent was busy on a long turn (queued, not yet read) all drain at
|
|
@@ -2751,7 +2782,7 @@ async function main() {
|
|
|
2751
2782
|
}
|
|
2752
2783
|
continue;
|
|
2753
2784
|
}
|
|
2754
|
-
if (line.startsWith("/revert")) {
|
|
2785
|
+
if (line.startsWith("/manual-edit") || line.startsWith("/revert")) {
|
|
2755
2786
|
const runId = line.split(/\s+/)[1] ?? "";
|
|
2756
2787
|
await new Promise((res) => {
|
|
2757
2788
|
const p = spawn(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiens.nguyen/gonext-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.368",
|
|
4
4
|
"description": "GoNext CLI — the gonext terminal plus the local worker that runs agent / OCR / PDF / embedding jobs on your Mac (Ollama / MLX / OpenAI-compatible).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|