@cruxy/cli 1.11.3 → 1.11.4
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/dist/cli/commands/run.js +9 -8
- package/dist/tui/renderer.js +59 -8
- package/package.json +1 -1
package/dist/cli/commands/run.js
CHANGED
|
@@ -359,15 +359,16 @@ export async function executeRun(promptParts, opts) {
|
|
|
359
359
|
}) ?? undefined;
|
|
360
360
|
// The TUI sidebar lists the same tree the `--resume` picker reads (P2).
|
|
361
361
|
//
|
|
362
|
-
// A
|
|
363
|
-
//
|
|
364
|
-
//
|
|
365
|
-
//
|
|
366
|
-
//
|
|
367
|
-
//
|
|
368
|
-
//
|
|
362
|
+
// A PROBE, NOT A LIST (cli#300). A fresh session is not on disk until its
|
|
363
|
+
// first turn — the meta line is buffered (#257) — so a list read here could
|
|
364
|
+
// never contain the session the user is in, and with no later caller the
|
|
365
|
+
// sidebar stayed exactly as stale as that first read for the whole run. The
|
|
366
|
+
// renderer re-runs this probe after every turn, off its paint path, so the
|
|
367
|
+
// running session appears the moment it lands and the tree keeps following
|
|
368
|
+
// what this and any other cruxy write. The active id marks the row when it
|
|
369
|
+
// shows; the sidebar and the picker still read the same ten.
|
|
369
370
|
if (renderer instanceof TuiRenderer) {
|
|
370
|
-
renderer.
|
|
371
|
+
renderer.attachSessions(() => listSessions(primaryRoot, SIDEBAR_SESSIONS), sessionId);
|
|
371
372
|
}
|
|
372
373
|
// ONE key reader for the whole TUI session (P5): the input loop and the
|
|
373
374
|
// approval prompt's modal both lease it, so the two can never be live on
|
package/dist/tui/renderer.js
CHANGED
|
@@ -219,14 +219,21 @@ export class TuiRenderer {
|
|
|
219
219
|
/**
|
|
220
220
|
* Saved sessions shown in the sidebar (P2), and which one is running.
|
|
221
221
|
*
|
|
222
|
-
* Populated
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
222
|
+
* Populated by {@link setSessions} or by the probe {@link attachSessions}
|
|
223
|
+
* installs, never at construction: the list is read from disk, the renderer
|
|
224
|
+
* is built before the session log exists, and a constructor argument could
|
|
225
|
+
* only ever carry the tree from BEFORE this run.
|
|
226
|
+
*
|
|
227
|
+
* THE LIST IS RE-READ AFTER EVERY TURN (cli#300). It used to be read once at
|
|
228
|
+
* startup, and since a fresh session's meta line is buffered until its first
|
|
229
|
+
* turn (#257), that one read could never include the session the user was
|
|
230
|
+
* in — the row the active id exists to mark. Re-probing on `endTurn`, the
|
|
231
|
+
* same trigger the git cache and the views use, is what lets it appear.
|
|
227
232
|
*/
|
|
228
233
|
sessions = [];
|
|
229
234
|
activeSessionId;
|
|
235
|
+
/** Re-reads the session tree; installed by {@link attachSessions}. */
|
|
236
|
+
sessionsProbe;
|
|
230
237
|
constructor(caps, out, opts = {}) {
|
|
231
238
|
this.caps = caps;
|
|
232
239
|
this.out = out;
|
|
@@ -573,9 +580,9 @@ export class TuiRenderer {
|
|
|
573
580
|
}
|
|
574
581
|
// ── app-owned surfaces ────────────────────────────────────────────────────
|
|
575
582
|
/**
|
|
576
|
-
* Replace the sidebar's session list (P2)
|
|
577
|
-
*
|
|
578
|
-
*
|
|
583
|
+
* Replace the sidebar's session list (P2) with one the caller already holds.
|
|
584
|
+
* The primitive {@link attachSessions} and {@link refreshSessions} both land
|
|
585
|
+
* on; a caller with no probe to install (tests, a static list) uses it alone.
|
|
579
586
|
*/
|
|
580
587
|
setSessions(sessions, activeSessionId) {
|
|
581
588
|
if (this.closed)
|
|
@@ -584,6 +591,46 @@ export class TuiRenderer {
|
|
|
584
591
|
this.activeSessionId = activeSessionId;
|
|
585
592
|
this.schedulePaint();
|
|
586
593
|
}
|
|
594
|
+
/**
|
|
595
|
+
* Install the probe that reads the session tree, and read it once now
|
|
596
|
+
* (cli#300). From here on {@link endTurn} re-runs it, so the list follows the
|
|
597
|
+
* tree as this and other cruxys write to it — and so the running session
|
|
598
|
+
* shows up the moment its first turn puts it on disk.
|
|
599
|
+
*
|
|
600
|
+
* THE PROBE NEVER RUNS ON THE PAINT PATH. It reads one meta line per file
|
|
601
|
+
* for at most ten files, which is cheap, and cheap is not the discipline:
|
|
602
|
+
* `viewModel` reads `this.sessions` and nothing else, exactly as it reads
|
|
603
|
+
* the git cache's last answer rather than running `git status`. A paint
|
|
604
|
+
* that touched the disk would do so on every streaming frame.
|
|
605
|
+
*/
|
|
606
|
+
attachSessions(probe, activeSessionId) {
|
|
607
|
+
if (this.closed)
|
|
608
|
+
return;
|
|
609
|
+
this.sessionsProbe = probe;
|
|
610
|
+
this.activeSessionId = activeSessionId;
|
|
611
|
+
this.refreshSessions();
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Re-read the session tree through the installed probe, off the paint path,
|
|
615
|
+
* and repaint if it answered. A probe that throws leaves the last list
|
|
616
|
+
* standing: the sidebar is a status surface, and a transient read error must
|
|
617
|
+
* never blank it or take the shell down. No probe → nothing to do, and the
|
|
618
|
+
* list set by {@link setSessions} stays as it was.
|
|
619
|
+
*/
|
|
620
|
+
refreshSessions() {
|
|
621
|
+
const probe = this.sessionsProbe;
|
|
622
|
+
if (probe === undefined || this.closed)
|
|
623
|
+
return;
|
|
624
|
+
let sessions;
|
|
625
|
+
try {
|
|
626
|
+
sessions = probe();
|
|
627
|
+
}
|
|
628
|
+
catch {
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
this.sessions = sessions;
|
|
632
|
+
this.schedulePaint();
|
|
633
|
+
}
|
|
587
634
|
/** Set the input line's rendered text (prompt + buffer + caret). */
|
|
588
635
|
setInput(line) {
|
|
589
636
|
if (this.closed)
|
|
@@ -865,6 +912,10 @@ export class TuiRenderer {
|
|
|
865
912
|
this.refreshGit();
|
|
866
913
|
this.refreshLimits();
|
|
867
914
|
this.refreshViews();
|
|
915
|
+
// AFTER the turn's final paint, like the three above: the frame that
|
|
916
|
+
// closes the turn is composed from state already in hand, and the tree
|
|
917
|
+
// read lands in the next scheduled paint rather than delaying this one.
|
|
918
|
+
this.refreshSessions();
|
|
868
919
|
}
|
|
869
920
|
/**
|
|
870
921
|
* REPAINT the headroom panel once the turn's reading lands (P9) — no longer
|