@tiens.nguyen/gonext-local-worker 1.0.262 → 1.0.263
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 +44 -33
- package/package.json +1 -1
package/gonext-repl.mjs
CHANGED
|
@@ -48,6 +48,9 @@ const white = (s) => `\x1b[37m${s}\x1b[0m`;
|
|
|
48
48
|
// code 34 (blue) which many dark-theme palettes render as purple/indigo instead.
|
|
49
49
|
const codeColor = (s) => `\x1b[90m${s}\x1b[0m`;
|
|
50
50
|
const bold = (s) => `\x1b[1m${s}\x1b[0m`;
|
|
51
|
+
// Hover highlight for the clickable thinking line (task #96): bold + underline + bright
|
|
52
|
+
// green so it reads as an interactive "link" the moment the mouse is over it.
|
|
53
|
+
const hoverThought = (s) => `\x1b[1;4;92m${s}\x1b[0m`;
|
|
51
54
|
|
|
52
55
|
// The worker's "still thinking" heartbeat lines look like "Caffeinating… (90s)" — we
|
|
53
56
|
// SWALLOW them from the terminal (the local ticker below drives progress instead), and
|
|
@@ -383,13 +386,15 @@ rl.on("close", () => {
|
|
|
383
386
|
w(null);
|
|
384
387
|
}
|
|
385
388
|
});
|
|
386
|
-
// Mouse click
|
|
387
|
-
//
|
|
388
|
-
// accepted: with tracking on, the terminal's
|
|
389
|
-
// user holds Option/Shift to select text
|
|
390
|
-
//
|
|
391
|
-
|
|
392
|
-
|
|
389
|
+
// Mouse hover+click on the thinking line (task #96): while a turn runs we turn ON xterm
|
|
390
|
+
// ANY-MOTION tracking so we can both HIGHLIGHT the line as the mouse hovers it AND expand it
|
|
391
|
+
// on click (see runAgentTurn). Trade-off the user accepted: with tracking on, the terminal's
|
|
392
|
+
// own drag-to-select/copy is captured by us — the user holds Option/Shift to select text
|
|
393
|
+
// meanwhile. ?1003 = report every button press/release AND all mouse MOTION (needed for hover
|
|
394
|
+
// with no button held); ?1006 = SGR extended coords (no 223-col cap). We disable ?1000/?1002
|
|
395
|
+
// too on teardown in case a terminal had them latched.
|
|
396
|
+
const MOUSE_ON = "\x1b[?1003h\x1b[?1006h";
|
|
397
|
+
const MOUSE_OFF = "\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?1006l";
|
|
393
398
|
let _mouseEnabled = false;
|
|
394
399
|
const enableMouse = () => {
|
|
395
400
|
if (_mouseEnabled || !process.stdin.isTTY) return;
|
|
@@ -404,8 +409,9 @@ const disableMouse = () => {
|
|
|
404
409
|
// Safety net: never leave the user's terminal in mouse-reporting mode (would break their
|
|
405
410
|
// shell's selection) if we exit ungracefully.
|
|
406
411
|
process.on("exit", disableMouse);
|
|
407
|
-
// SGR mouse report: ESC [ < btn ; col ; row (M=press, m=release).
|
|
408
|
-
//
|
|
412
|
+
// SGR mouse report: ESC [ < btn ; col ; row (M=press, m=release). btn bit 32 = MOTION
|
|
413
|
+
// (hover/drag), bit 64 = wheel; low 2 bits = which button (0=left). A left CLICK is a press
|
|
414
|
+
// (M) with motion+wheel bits clear and low bits 0; a HOVER is any event with the motion bit.
|
|
409
415
|
const MOUSE_RE = /\x1b\[<(\d+);(\d+);(\d+)([Mm])/g;
|
|
410
416
|
const nextLine = () =>
|
|
411
417
|
_lineQueue.length > 0
|
|
@@ -1213,6 +1219,7 @@ async function runAgentTurn(history) {
|
|
|
1213
1219
|
// whether the user has clicked to expand it. Both reset when the step's Thought changes.
|
|
1214
1220
|
let fullLiveThought = "";
|
|
1215
1221
|
let thoughtExpanded = false;
|
|
1222
|
+
let hoverRow = -1; // last mouse viewport row (from motion events) → highlight when it's on the thought line
|
|
1216
1223
|
const thinkSecs = () => Math.max(1, Math.round((Date.now() - thinkingSince) / 1000));
|
|
1217
1224
|
|
|
1218
1225
|
// The status is normally TWO in-place lines — the in-progress action, then the playful
|
|
@@ -1267,28 +1274,30 @@ async function runAgentTurn(history) {
|
|
|
1267
1274
|
: liveThought || (almostDone ? "Almost done" : "Thinking");
|
|
1268
1275
|
const max = Math.max(24, (process.stdout.columns || 80) - 14);
|
|
1269
1276
|
const fit = (s) => (s.length > max ? s.slice(0, max - 1) + "…" : s);
|
|
1270
|
-
clearStatus();
|
|
1271
|
-
// Line 1: green ● + green phase/seconds (matches the web's green streaming label).
|
|
1272
|
-
// Line 2 (indented): the SPINNER + the playful word together, both in the cycling
|
|
1273
|
-
// color — the spinner belongs with the word (dot on the label line, spinner leading
|
|
1274
|
-
// the flavor line).
|
|
1275
|
-
// Task #83/#84: after the playful word, show the running agent-code-model token
|
|
1276
|
-
// count (dim) plus the per-workspace PEAK single-request count (orange), e.g.
|
|
1277
|
-
// " ⠙ Caffeinating… · 12.3k tok · 8.1k max". Both start at 0 and climb.
|
|
1278
1277
|
const tokLabel =
|
|
1279
1278
|
dim(` · ${fmtTokens(latestCodeTokens)} tok`) +
|
|
1280
1279
|
orange(` · ${fmtTokens(sessionMaxCodeTokens)} max`);
|
|
1280
|
+
// Task #96: the thought line is "clickable" only when there's a fuller thought to reveal
|
|
1281
|
+
// (a live command / bare "Thinking" has nothing to expand). When clicked, unfold it below
|
|
1282
|
+
// as up to 4 wrapped GREY lines (dim). The whole status block rides the viewport bottom as
|
|
1283
|
+
// output scrolls, so line 1 (the thought) sits at row `rows - drawn + 1` — if the mouse is
|
|
1284
|
+
// hovering THAT row, render the label as an underlined bright-green "link".
|
|
1285
|
+
const clickable = !!(fullLiveThought && !runningCmd);
|
|
1286
|
+
const expLines = thoughtExpanded && clickable ? wrapThought(fullLiveThought, max, 4) : [];
|
|
1287
|
+
const drawn = 2 + expLines.length;
|
|
1288
|
+
const rows = process.stdout.rows || 24;
|
|
1289
|
+
const hovering = clickable && hoverRow === rows - drawn + 1;
|
|
1290
|
+
const label = `${fit(primary)}… (${secs}s)`;
|
|
1291
|
+
clearStatus();
|
|
1292
|
+
// Line 1: green ● + green phase/seconds (matches the web's green streaming label), or the
|
|
1293
|
+
// underlined bright-green hover style when the mouse is over a clickable thought.
|
|
1294
|
+
// Line 2 (indented): the SPINNER + the playful word together, both in the cycling color.
|
|
1295
|
+
// Task #83/#84: after the word, the running agent-code token count (dim) + per-workspace
|
|
1296
|
+
// PEAK single-request count (orange), e.g. " ⠙ Caffeinating… · 12.3k tok · 8.1k max".
|
|
1281
1297
|
let out =
|
|
1282
|
-
`${green(BULLET)} ${
|
|
1298
|
+
`${green(BULLET)} ${hovering ? hoverThought(label) : green(label)}` +
|
|
1283
1299
|
"\n" + ` ${color256(wc, `${glyph} ${thinkWord}…`)}${tokLabel}`;
|
|
1284
|
-
|
|
1285
|
-
// Task #96: when the user has clicked the thought line, unfold the fuller thought below
|
|
1286
|
-
// it as up to 4 wrapped GREY lines (dim). Only when there's genuinely more to show than
|
|
1287
|
-
// the truncated primary (a live command / bare "Thinking" has nothing to expand).
|
|
1288
|
-
if (thoughtExpanded && fullLiveThought && !runningCmd) {
|
|
1289
|
-
const wrapped = wrapThought(fullLiveThought, max, 4);
|
|
1290
|
-
for (const wl of wrapped) { out += "\n " + dim(wl); drawn++; }
|
|
1291
|
-
}
|
|
1300
|
+
for (const wl of expLines) out += "\n " + dim(wl);
|
|
1292
1301
|
process.stdout.write(out);
|
|
1293
1302
|
statusLines = drawn;
|
|
1294
1303
|
statusShown = true;
|
|
@@ -1297,12 +1306,13 @@ async function runAgentTurn(history) {
|
|
|
1297
1306
|
// seconds still tick once/sec). Only redraws when the model has gone quiet >QUIET_MS.
|
|
1298
1307
|
const ticker = setInterval(tick, 120);
|
|
1299
1308
|
|
|
1300
|
-
// ---
|
|
1301
|
-
//
|
|
1302
|
-
//
|
|
1303
|
-
//
|
|
1304
|
-
//
|
|
1305
|
-
//
|
|
1309
|
+
// --- Hover + click on the thinking line (task #96) -------------------------------------
|
|
1310
|
+
// HOVER: motion events keep `hoverRow`; the tick highlights the thought line (underlined
|
|
1311
|
+
// bright-green "link") whenever the mouse is on its row. CLICK: a left-click on the status
|
|
1312
|
+
// block toggles the fuller thought (3-4 grey lines). The block sits at the bottom of the
|
|
1313
|
+
// viewport (new output keeps scrolling it there), so we hit-test rows against the bottom
|
|
1314
|
+
// `statusLines` rows. Mouse reporting is on only for the turn and always turned back off in
|
|
1315
|
+
// the finally + on process exit, so the user's shell is never left in mouse-capture mode.
|
|
1306
1316
|
const onStatusClick = (row) => {
|
|
1307
1317
|
if (!statusShown) return;
|
|
1308
1318
|
const rows = process.stdout.rows || 24;
|
|
@@ -1324,7 +1334,8 @@ async function runAgentTurn(history) {
|
|
|
1324
1334
|
const btn = parseInt(m[1], 10);
|
|
1325
1335
|
const row = parseInt(m[3], 10);
|
|
1326
1336
|
const isPress = m[4] === "M";
|
|
1327
|
-
if (
|
|
1337
|
+
if (btn & 32) { hoverRow = row; continue; } // MOTION (hover/drag) → track for the highlight
|
|
1338
|
+
if (isPress && (btn & 0b11) === 0 && (btn & 64) === 0) onStatusClick(row); // left click → expand
|
|
1328
1339
|
}
|
|
1329
1340
|
};
|
|
1330
1341
|
if (process.stdin.isTTY) process.stdin.on("data", onMouseData);
|
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.263",
|
|
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",
|