@tiens.nguyen/gonext-local-worker 1.0.208 → 1.0.210
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 +64 -10
- package/package.json +1 -1
package/gonext-repl.mjs
CHANGED
|
@@ -159,8 +159,46 @@ if (!workerKey || !apiBase) {
|
|
|
159
159
|
// editing didn't work at all (user-reported). Giving readline the prompt makes its
|
|
160
160
|
// redraw math correct — rl.prompt() resets the cursor state after every burst of our
|
|
161
161
|
// output — and raw mode means backspace/arrows/↑-history all behave like a normal shell.
|
|
162
|
+
// Single source of truth for the REPL's slash commands — drives Tab-completion, the
|
|
163
|
+
// unknown-command guard, and /help, so they can never drift.
|
|
164
|
+
const COMMANDS = [
|
|
165
|
+
{ name: "/model", desc: "switch the coding model for this session" },
|
|
166
|
+
{ name: "/revert", usage: "/revert [runId]", desc: "undo the agent's file edits (latest run)" },
|
|
167
|
+
{ name: "/reset", aliases: ["/new"], desc: "forget this folder's saved conversation and start fresh" },
|
|
168
|
+
{ name: "/help", desc: "list these commands" },
|
|
169
|
+
{ name: "/exit", aliases: ["/quit"], desc: "quit" },
|
|
170
|
+
];
|
|
171
|
+
const COMMAND_NAMES = COMMANDS.flatMap((c) => [c.name, ...(c.aliases ?? [])]);
|
|
172
|
+
// Tab-completion: when the line starts with "/", complete against the command names.
|
|
173
|
+
function slashCompleter(line) {
|
|
174
|
+
if (!line.startsWith("/")) return [[], line];
|
|
175
|
+
const hits = COMMAND_NAMES.filter((n) => n.startsWith(line));
|
|
176
|
+
return [hits.length ? hits : COMMAND_NAMES, line];
|
|
177
|
+
}
|
|
178
|
+
function printCommands(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
|
+
console.log(dim(" commands (Tab completes):"));
|
|
187
|
+
for (const c of show.length ? show : COMMANDS) {
|
|
188
|
+
const label = c.usage ?? c.name;
|
|
189
|
+
const alias = c.aliases?.length ? dim(` (${c.aliases.join(", ")})`) : "";
|
|
190
|
+
console.log(` ${cyan(label)}${alias}${dim(" — " + c.desc)}`);
|
|
191
|
+
}
|
|
192
|
+
console.log("");
|
|
193
|
+
}
|
|
194
|
+
|
|
162
195
|
const IS_TTY = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
163
|
-
const rl = createInterface({
|
|
196
|
+
const rl = createInterface({
|
|
197
|
+
input: process.stdin,
|
|
198
|
+
output: process.stdout,
|
|
199
|
+
terminal: IS_TTY,
|
|
200
|
+
completer: slashCompleter,
|
|
201
|
+
});
|
|
164
202
|
const PROMPT = cyan(">> ");
|
|
165
203
|
rl.setPrompt(PROMPT);
|
|
166
204
|
// Side effect of terminal:false above: readline no longer intercepts arrow keys for
|
|
@@ -205,12 +243,27 @@ rl.on("line", (l) => {
|
|
|
205
243
|
// turn: echo is already muted, but readline still recalls history into the invisible
|
|
206
244
|
// buffer on ↑/↓ — reset the line state after every keypress so nothing accumulates or
|
|
207
245
|
// moves. Ctrl+C is unaffected (readline emits its SIGINT before this handler runs).
|
|
246
|
+
let slashHintShown = false; // the live command hint is currently displayed for a "/…" line
|
|
208
247
|
if (process.stdin.isTTY) {
|
|
209
248
|
process.stdin.on("keypress", () => {
|
|
210
249
|
if (following) {
|
|
211
250
|
rl.line = "";
|
|
212
251
|
rl.cursor = 0;
|
|
213
252
|
rl.historyIndex = -1;
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
// Live command hint: the moment the line starts with "/", pop the command list ABOVE
|
|
256
|
+
// the prompt (once) so the user sees /model etc. without typing the whole thing or
|
|
257
|
+
// pressing Tab. Shown once per "/…" run; cleared/reset when the line stops being a
|
|
258
|
+
// slash command (so a fresh "/" shows it again).
|
|
259
|
+
const l = rl.line;
|
|
260
|
+
if (l.startsWith("/") && !slashHintShown) {
|
|
261
|
+
slashHintShown = true;
|
|
262
|
+
process.stdout.write("\r\x1b[K"); // wipe the ">> /" input row
|
|
263
|
+
printCommands(l); // list where the prompt was + below
|
|
264
|
+
rl._refreshLine(); // redraw ">> /" (with cursor) beneath the list
|
|
265
|
+
} else if (!l.startsWith("/")) {
|
|
266
|
+
slashHintShown = false;
|
|
214
267
|
}
|
|
215
268
|
});
|
|
216
269
|
}
|
|
@@ -916,7 +969,7 @@ async function main() {
|
|
|
916
969
|
console.error(red(`gonext: ${err.message}`));
|
|
917
970
|
process.exit(1);
|
|
918
971
|
}
|
|
919
|
-
console.log(dim("Ask about this repo
|
|
972
|
+
console.log(dim("Ask about this repo. Type / to see commands (Tab completes). Ctrl-C aborts a running turn.\n"));
|
|
920
973
|
|
|
921
974
|
const cwd = resolve(process.cwd());
|
|
922
975
|
const history = await loadSession(cwd);
|
|
@@ -979,14 +1032,8 @@ async function main() {
|
|
|
979
1032
|
if (lineRaw === null) break; // stdin closed
|
|
980
1033
|
const line = lineRaw.trim();
|
|
981
1034
|
if (line === "/exit" || line === "/quit") break;
|
|
982
|
-
if (line === "/help") {
|
|
983
|
-
|
|
984
|
-
dim(
|
|
985
|
-
" /exit — quit · /model — switch the coding model for this session · " +
|
|
986
|
-
"/revert [runId] — undo the agent's file edits (latest run) · " +
|
|
987
|
-
"/reset — forget this folder's saved conversation and start fresh"
|
|
988
|
-
)
|
|
989
|
-
);
|
|
1035
|
+
if (line === "/" || line === "/help") {
|
|
1036
|
+
printCommands();
|
|
990
1037
|
continue;
|
|
991
1038
|
}
|
|
992
1039
|
if (line === "/model") {
|
|
@@ -1012,6 +1059,13 @@ async function main() {
|
|
|
1012
1059
|
});
|
|
1013
1060
|
continue;
|
|
1014
1061
|
}
|
|
1062
|
+
// Any OTHER "/…" is a typo/unknown command — don't send it to the agent as a
|
|
1063
|
+
// question; point the user at /help (all real commands were handled above).
|
|
1064
|
+
if (line.startsWith("/")) {
|
|
1065
|
+
const cmd = line.split(/\s+/)[0];
|
|
1066
|
+
console.log(dim(`unknown command: ${cmd} — type /help (or / then Tab) to list commands\n`));
|
|
1067
|
+
continue;
|
|
1068
|
+
}
|
|
1015
1069
|
history.push({ role: "user", content: line });
|
|
1016
1070
|
try {
|
|
1017
1071
|
const { text: answer, shown, cancelled } = await runAgentTurn(history);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiens.nguyen/gonext-local-worker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.210",
|
|
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",
|