@tiens.nguyen/gonext-local-worker 1.0.240 → 1.0.241
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 +37 -7
- package/package.json +1 -1
package/gonext-repl.mjs
CHANGED
|
@@ -106,8 +106,22 @@ const THINKING_WORDS = (() => {
|
|
|
106
106
|
})();
|
|
107
107
|
const pickWord = () =>
|
|
108
108
|
THINKING_WORDS[Math.floor(Math.random() * THINKING_WORDS.length)] || "Thinking";
|
|
109
|
-
//
|
|
110
|
-
|
|
109
|
+
// In-progress ("blinking") spinner for the step being worked on. 30 styles that rotate
|
|
110
|
+
// ~every 8s so a long CPU-bound wait stays interesting — mirrors the web agent's set
|
|
111
|
+
// (keep in sync with the .spin-N @keyframes in web/src/App.css). Single-width glyphs so
|
|
112
|
+
// they never shift the text after them.
|
|
113
|
+
const SPINNERS = [
|
|
114
|
+
"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏", "│╱─╲", "▁▃▄▅▆▇▆▅▄▃", "←↖↑↗→↘↓↙", "▏▎▍▌▋▊▉▊▋▌▍▎",
|
|
115
|
+
"◴◷◶◵", "◐◓◑◒", "⣾⣽⣻⢿⡿⣟⣯⣷", "▖▘▝▗", "✶✸✹✺✹✷",
|
|
116
|
+
"⠁⠂⠄⡀⢀⠠⠐⠈", "dqpb", "◢◣◤◥", "✦✧", "◜◝◞◟",
|
|
117
|
+
"▌▀▐▄", "◰◳◲◱", "┤┘┴└├┌┬┐", "▘▝▗▖", "▸▹",
|
|
118
|
+
"⢄⢂⢁⡁⡈⡐⡠", "▙▛▜▟", "▂▃▄▅▆▇█▇▆▅▄▃", "⣿⣷⣯⣟⡿⢿⣻⣽", "⎺⎻⎼⎽",
|
|
119
|
+
"•◦", "░▒▓█▓▒", "◇◈◆", "·✢✳✽", "◠◡",
|
|
120
|
+
].map((s) => [...s]);
|
|
121
|
+
// The playful word's color cycles ~every 2.5s (xterm-256 palette matching the web accents:
|
|
122
|
+
// green, cyan, blue, indigo, pink, amber).
|
|
123
|
+
const WAIT_COLORS_256 = [120, 87, 111, 147, 218, 221];
|
|
124
|
+
const color256 = (n, s) => `\x1b[38;5;${n}m${s}\x1b[0m`;
|
|
111
125
|
const BULLET = "●"; // a completed action
|
|
112
126
|
|
|
113
127
|
// ---------- flags ----------
|
|
@@ -1014,6 +1028,7 @@ async function runAgentTurn(history) {
|
|
|
1014
1028
|
let thinking = false;
|
|
1015
1029
|
let thinkingSince = 0;
|
|
1016
1030
|
let thinkWord = pickWord(); // playful word shown UNDER the in-progress line (flavor)
|
|
1031
|
+
let lastWordBucket = -1; // 12s window index → rotate the word once per window (task: 30-spinner)
|
|
1017
1032
|
let almostDone = false; // set from the worker's "…almost completed thinking…" heartbeat
|
|
1018
1033
|
let runningCmd = null; // the command currently executing (from a "Running → …" event)
|
|
1019
1034
|
// The model's CURRENT Thought (task #64): while it streams its reasoning inside the
|
|
@@ -1042,10 +1057,20 @@ async function runAgentTurn(history) {
|
|
|
1042
1057
|
// silent once any of THIS line has already been shown (see carryFlushedLen).
|
|
1043
1058
|
if (plainReplyFlow && carryFlushedLen > 0) return;
|
|
1044
1059
|
// Count from when this phase went quiet, so the seconds reflect the current wait/run.
|
|
1045
|
-
if (!thinking) {
|
|
1060
|
+
if (!thinking) {
|
|
1061
|
+
thinking = true; thinkingSince = lastContentAt; thinkWord = pickWord(); lastWordBucket = 0;
|
|
1062
|
+
}
|
|
1063
|
+
const now = Date.now();
|
|
1046
1064
|
const secs = thinkSecs();
|
|
1047
|
-
|
|
1048
|
-
|
|
1065
|
+
// Rotate the playful word once per 12s window (guarded so the fast ticker doesn't
|
|
1066
|
+
// re-roll it many times within the same second).
|
|
1067
|
+
const wordBucket = Math.floor((now - thinkingSince) / 12000);
|
|
1068
|
+
if (wordBucket !== lastWordBucket) { lastWordBucket = wordBucket; thinkWord = pickWord(); }
|
|
1069
|
+
// Spinner: STYLE rotates ~every 8s, FRAME advances ~every 120ms, color cycles ~every
|
|
1070
|
+
// 2.5s — all off the wall clock so they keep moving smoothly across phases.
|
|
1071
|
+
const frames = SPINNERS[Math.floor(now / 8000) % SPINNERS.length];
|
|
1072
|
+
const glyph = frames[Math.floor(now / 120) % frames.length];
|
|
1073
|
+
const wc = WAIT_COLORS_256[Math.floor(now / 2500) % WAIT_COLORS_256.length];
|
|
1049
1074
|
// Line 1 = WHAT is happening now: the running command, else the phase (Thinking /
|
|
1050
1075
|
// Almost done). Line 2 = the playful word (flavor). Truncate so neither wraps.
|
|
1051
1076
|
// Priority: a live command > the model's current Thought clause (task #64, so a
|
|
@@ -1057,12 +1082,17 @@ async function runAgentTurn(history) {
|
|
|
1057
1082
|
const max = Math.max(24, (process.stdout.columns || 80) - 14);
|
|
1058
1083
|
const fit = (s) => (s.length > max ? s.slice(0, max - 1) + "…" : s);
|
|
1059
1084
|
clearStatus();
|
|
1085
|
+
// Line 1: cycling-color spinner + yellow phase/seconds. Line 2: the word in the same
|
|
1086
|
+
// cycling color (the web colors the spinner + word together; primary stays the theme).
|
|
1060
1087
|
process.stdout.write(
|
|
1061
|
-
|
|
1088
|
+
`${color256(wc, glyph)} ${yellow(`${fit(primary)}… (${secs}s)`)}` +
|
|
1089
|
+
"\n" + color256(wc, ` ${thinkWord}…`)
|
|
1062
1090
|
);
|
|
1063
1091
|
statusShown = true;
|
|
1064
1092
|
};
|
|
1065
|
-
|
|
1093
|
+
// 120ms so the spinner animates smoothly (the frame math above uses the wall clock, so
|
|
1094
|
+
// seconds still tick once/sec). Only redraws when the model has gone quiet >QUIET_MS.
|
|
1095
|
+
const ticker = setInterval(tick, 120);
|
|
1066
1096
|
|
|
1067
1097
|
// Called right before any real (bullet/edit-card/answer) content prints: drop the
|
|
1068
1098
|
// status lines so content lands cleanly, and end the current phase (so the next phase's
|
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.241",
|
|
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",
|