@tiens.nguyen/gonext-local-worker 1.0.225 → 1.0.226
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 +51 -6
- package/package.json +1 -1
package/gonext-repl.mjs
CHANGED
|
@@ -699,6 +699,21 @@ async function runAgentTurn(history) {
|
|
|
699
699
|
let thinkWord = pickWord(); // playful word shown UNDER the in-progress line (flavor)
|
|
700
700
|
let almostDone = false; // set from the worker's "…almost completed thinking…" heartbeat
|
|
701
701
|
let runningCmd = null; // the command currently executing (from a "Running → …" event)
|
|
702
|
+
// The model's CURRENT Thought (task #64): while it streams its reasoning inside the
|
|
703
|
+
// hidden ~~~ fence, show a one-clause summary on the blinking line so a 300s CPU-bound
|
|
704
|
+
// step reads as "◑ Adding the nav links to app.component.html… (52s)" instead of a
|
|
705
|
+
// random word. `fenceThought` accumulates the raw in-fence text for the current step.
|
|
706
|
+
let liveThought = "";
|
|
707
|
+
let fenceThought = "";
|
|
708
|
+
// First non-empty Thought clause: drop the "Thought:" prefix, stop at the <code> block
|
|
709
|
+
// (we never show code), take the first line, and cap length so it never wraps.
|
|
710
|
+
const extractThought = (buf) => {
|
|
711
|
+
let t = String(buf || "");
|
|
712
|
+
const ci = t.search(/<code[\s>]/i);
|
|
713
|
+
if (ci >= 0) t = t.slice(0, ci);
|
|
714
|
+
t = t.replace(/^\s*Thought:\s*/i, "").split(/\n/)[0].trim();
|
|
715
|
+
return t;
|
|
716
|
+
};
|
|
702
717
|
const thinkSecs = () => Math.max(1, Math.round((Date.now() - thinkingSince) / 1000));
|
|
703
718
|
|
|
704
719
|
// The status is TWO in-place lines — the in-progress action, then the playful word
|
|
@@ -724,9 +739,12 @@ async function runAgentTurn(history) {
|
|
|
724
739
|
const glyph = SPINNER[secs % SPINNER.length]; // rotates → reads as "in progress"
|
|
725
740
|
// Line 1 = WHAT is happening now: the running command, else the phase (Thinking /
|
|
726
741
|
// Almost done). Line 2 = the playful word (flavor). Truncate so neither wraps.
|
|
742
|
+
// Priority: a live command > the model's current Thought clause (task #64, so a
|
|
743
|
+
// long CPU-bound step reads as what it's actually reasoning about, not "Thinking")
|
|
744
|
+
// > the "almost done" heartbeat > the bare fallback.
|
|
727
745
|
const primary = runningCmd
|
|
728
746
|
? `Running ${runningCmd}`
|
|
729
|
-
: almostDone ? "Almost done" : "Thinking";
|
|
747
|
+
: liveThought || (almostDone ? "Almost done" : "Thinking");
|
|
730
748
|
const max = Math.max(24, (process.stdout.columns || 80) - 14);
|
|
731
749
|
const fit = (s) => (s.length > max ? s.slice(0, max - 1) + "…" : s);
|
|
732
750
|
clearStatus();
|
|
@@ -744,6 +762,10 @@ async function runAgentTurn(history) {
|
|
|
744
762
|
clearStatus();
|
|
745
763
|
thinking = false;
|
|
746
764
|
runningCmd = null;
|
|
765
|
+
// A concrete action landed → the Thought that led to it is spent; clear it so the
|
|
766
|
+
// next step's blinking line starts from "Thinking", not last step's stale clause.
|
|
767
|
+
liveThought = "";
|
|
768
|
+
fenceThought = "";
|
|
747
769
|
lastContentAt = Date.now();
|
|
748
770
|
};
|
|
749
771
|
|
|
@@ -782,11 +804,26 @@ async function runAgentTurn(history) {
|
|
|
782
804
|
almostDone = /almost/i.test(line);
|
|
783
805
|
continue;
|
|
784
806
|
}
|
|
785
|
-
|
|
786
|
-
//
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
807
|
+
// A fence opening starts a fresh step's raw stream → reset the harvested Thought
|
|
808
|
+
// so the blinking line doesn't carry last step's clause into this one.
|
|
809
|
+
if (isFenceLine(line)) {
|
|
810
|
+
inStreamFence = !inStreamFence;
|
|
811
|
+
if (inStreamFence) fenceThought = "";
|
|
812
|
+
continue;
|
|
813
|
+
}
|
|
814
|
+
// Inside a ~~~ fence = raw model Thought/code stream → suppressed from scrollback. Do
|
|
815
|
+
// NOT bump lastContentAt: while the (now hidden) tokens flow, the blinking bullet keeps
|
|
816
|
+
// ticking so the user sees the step is still being worked on. But HARVEST the first
|
|
817
|
+
// Thought clause for the blinking line (task #64) — up to the <code> block, which is
|
|
818
|
+
// where the prose ends and the tool call begins (we never surface code here).
|
|
819
|
+
if (inStreamFence) {
|
|
820
|
+
if (!/<code[\s>]/i.test(fenceThought)) {
|
|
821
|
+
fenceThought += line + "\n";
|
|
822
|
+
const th = extractThought(fenceThought);
|
|
823
|
+
if (th) liveThought = th;
|
|
824
|
+
}
|
|
825
|
+
continue;
|
|
826
|
+
}
|
|
790
827
|
if (isToolStepSummary(line)) { lastContentAt = Date.now(); continue; } // swallow
|
|
791
828
|
if (isRoutingLine(line)) {
|
|
792
829
|
// Swallow the router's play-by-play entirely — the blinking-bullet ticker (which
|
|
@@ -914,6 +951,14 @@ async function runAgentTurn(history) {
|
|
|
914
951
|
answerShownLive = true;
|
|
915
952
|
lastWasBlank = false;
|
|
916
953
|
}
|
|
954
|
+
// While in the hidden fence, the model's FIRST Thought line often sits in `carry` with
|
|
955
|
+
// no newline yet (a long reasoning sentence streams token-by-token) — recompute the
|
|
956
|
+
// live clause from the partial too, so the blinking line updates mid-sentence instead
|
|
957
|
+
// of only once the line finally breaks (task #64).
|
|
958
|
+
if (inStreamFence && !/<code[\s>]/i.test(fenceThought)) {
|
|
959
|
+
const th = extractThought(fenceThought + carry);
|
|
960
|
+
if (th) liveThought = th;
|
|
961
|
+
}
|
|
917
962
|
// A non-empty remainder is a partial CONTENT line (heartbeats always arrive whole with
|
|
918
963
|
// a newline), so tokens are actively flowing — keep the ticker asleep.
|
|
919
964
|
if (carry.trim() !== "") lastContentAt = Date.now();
|
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.226",
|
|
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",
|