bermudis-pi-goodies 0.13.0 → 0.13.2
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/README.md +39 -1
- package/clean-tui.ts +35 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ extensions. One entry point, eleven independent features.
|
|
|
23
23
|
After publishing the package to npm:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
pi install npm:bermudis-pi-goodies@0.13.
|
|
26
|
+
pi install npm:bermudis-pi-goodies@0.13.2
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Remove any old `bermudis-pi-goodies.ts` symlink before reloading Pi. Each
|
|
@@ -67,6 +67,44 @@ Failures degrade gracefully: the raw command stays visible as a heuristic
|
|
|
67
67
|
hint, each distinct failure is logged once (naming the model), and repeated
|
|
68
68
|
failures back off exponentially instead of hammering the provider.
|
|
69
69
|
|
|
70
|
+
### Render-safety rules (why summaries only refresh running rows)
|
|
71
|
+
|
|
72
|
+
These rules apply to pi's **regular** TUI mode (`tuiMode: "regular"`, the
|
|
73
|
+
default — `TuiMainScreen`, the scrolling scrollback renderer). Pi also has a
|
|
74
|
+
**fullscreen** mode (`TuiAltScreen`): no scrollback, a fixed `height`-line
|
|
75
|
+
slice of the transcript diffed row-by-row, full clears only on first
|
|
76
|
+
render/resize/image redraws. Neither escalation below exists there — a
|
|
77
|
+
summary arrival re-rendering an old row is either invisible (scrolled off
|
|
78
|
+
the slice) or a one-line rewrite. Check `~/.pi/agent/settings.json`
|
|
79
|
+
`tuiMode` before reasoning about render escalation.
|
|
80
|
+
|
|
81
|
+
Pi's regular-mode diff renderer answers two situations with
|
|
82
|
+
`fullRender(true)` — clear screen, wipe scrollback, repaint everything —
|
|
83
|
+
which reads as a full-screen flash:
|
|
84
|
+
|
|
85
|
+
1. total rendered height dropping below the session high-water mark
|
|
86
|
+
(`clearOnShrink`), and
|
|
87
|
+
2. any content change to a line **above the scrolled viewport**
|
|
88
|
+
(`firstChanged < prevViewportTop` — width-independent; on a long
|
|
89
|
+
transcript this is any row more than a screenful above the input box).
|
|
90
|
+
|
|
91
|
+
clean-tui therefore follows two rules in its render paths:
|
|
92
|
+
|
|
93
|
+
- **Height-neutral swaps:** text that may be replaced by a summary later is
|
|
94
|
+
capped at the same width as summaries (`BASH_BULLET_WIDTH`), so an
|
|
95
|
+
arriving summary never collapses a wrapped line (rule 1).
|
|
96
|
+
- **Pending-only refresh:** when a summary lands, only rows whose tool is
|
|
97
|
+
still executing are re-rendered — those sit at the transcript tail, inside
|
|
98
|
+
the viewport, so the swap is a cheap differential update. Finished rows
|
|
99
|
+
(including replayed ones from before a `/resume`) keep the raw command
|
|
100
|
+
text for the rest of the session; the summary stays cached, and future
|
|
101
|
+
rows of the same command render it from the start (rule 2).
|
|
102
|
+
|
|
103
|
+
To catch a flash red-handed, run `PI_DEBUG_REDRAW=1 pi`, reproduce, then
|
|
104
|
+
`grep fullRender ~/.pi/agent/pi-debug.log` — every line is one screen wipe
|
|
105
|
+
with its reason (`clearOnShrink`, `firstChanged < viewportTop`, resize, …).
|
|
106
|
+
Note the log is append-only across sessions; check timestamps.
|
|
107
|
+
|
|
70
108
|
## Per-model thinking levels (retired in favor of Pi 0.84.3)
|
|
71
109
|
|
|
72
110
|
This package previously shipped a `model-thinking` module with a `/levels`
|
package/clean-tui.ts
CHANGED
|
@@ -537,8 +537,19 @@ function requestSummary(cmd: string): void {
|
|
|
537
537
|
}
|
|
538
538
|
|
|
539
539
|
function invalidateRowsForCommand(cmd: string): void {
|
|
540
|
+
// Only rows that are STILL EXECUTING get refreshed when a summary lands.
|
|
541
|
+
// Executing rows sit at the transcript tail, inside pi's viewport, so the
|
|
542
|
+
// re-render is a cheap differential line update. Finished rows — including
|
|
543
|
+
// replayed ones from before a /resume — can sit far above the viewport on a
|
|
544
|
+
// long transcript, and pi's diff renderer answers any change above the
|
|
545
|
+
// viewport with fullRender(true): clear screen + scrollback wipe + full
|
|
546
|
+
// repaint, i.e. the "flicker while pi is working" seen on 0.11.x (fits any
|
|
547
|
+
// width; reproduced reasoning from tui-main-screen.js `firstChanged <
|
|
548
|
+
// prevViewportTop`). Finished rows simply keep the raw command text, which
|
|
549
|
+
// is more informative than the summary anyway; the summary stays cached
|
|
550
|
+
// and future rows of the same command render it from the start.
|
|
540
551
|
for (const e of entries) {
|
|
541
|
-
if (e.args?.command === cmd) {
|
|
552
|
+
if (!e.result && e.args?.command === cmd) {
|
|
542
553
|
const fn = invalidateById.get(e.toolCallId);
|
|
543
554
|
if (fn) fn();
|
|
544
555
|
}
|
|
@@ -621,15 +632,24 @@ function formatBashHeader(args: any, theme: any): string {
|
|
|
621
632
|
if (isSummarizable(cmd) && summaryCache.has(cmd)) {
|
|
622
633
|
return theme.fg("accent", summaryCache.get(cmd)!);
|
|
623
634
|
}
|
|
624
|
-
|
|
635
|
+
// Cap must match BASH_BULLET_WIDTH, not exceed it: when a summary lands it
|
|
636
|
+
// replaces this text, and summaries are capped at SUMMARY_THRESHOLD_CHARS.
|
|
637
|
+
// A larger raw cap means the raw header can wrap where the summary won't,
|
|
638
|
+
// so the swap shrinks total line count mid-run — and pi-tui answers any
|
|
639
|
+
// drop below its high-water mark with a full clear-screen + scrollback wipe
|
|
640
|
+
// (clearOnShrink), i.e. a visible full-screen flash per summarized command
|
|
641
|
+
// (reproduced in panes narrower than ~124 cols; see clean-tui.test.ts
|
|
642
|
+
// "summary swap is height-neutral at 110 columns"). Equal caps keep the
|
|
643
|
+
// swap height-neutral wherever 80 columns fit.
|
|
644
|
+
return formatBashCommand(cmd, theme, BASH_BULLET_WIDTH);
|
|
625
645
|
}
|
|
626
646
|
|
|
627
647
|
function formatBashBullet(entry: Entry, theme: any): string {
|
|
628
648
|
const cmd = entry.args.command || "...";
|
|
629
649
|
const bullet = `${theme.fg("muted", "•")} `;
|
|
630
650
|
// Failed calls get red text so a single failure is visible without
|
|
631
|
-
// poisoning the whole burst's background (see renderCall:
|
|
632
|
-
//
|
|
651
|
+
// poisoning the whole burst's background (see renderCall: the grouped box
|
|
652
|
+
// never takes the error color, whichever call failed).
|
|
633
653
|
const accent = (s: string) => theme.fg(entry.isError ? "error" : "accent", s);
|
|
634
654
|
if (isSummarizable(cmd) && summaryCache.has(cmd)) {
|
|
635
655
|
return ` ${bullet}${accent(summaryCache.get(cmd)!)}`;
|
|
@@ -875,12 +895,17 @@ export default function cleanTui(pi: ExtensionAPI): void {
|
|
|
875
895
|
const isGrouped = burst && burst.entries.length > 1;
|
|
876
896
|
const isLeader =
|
|
877
897
|
isGrouped && burst.entries[0].toolCallId === ctx.toolCallId;
|
|
878
|
-
//
|
|
879
|
-
//
|
|
880
|
-
//
|
|
881
|
-
// (
|
|
882
|
-
|
|
883
|
-
|
|
898
|
+
// The burst box is shared by every call in the group, so its background
|
|
899
|
+
// never takes the error color — a failure (the leader included) is
|
|
900
|
+
// marked on its own bullet instead (formatBashBullet). "Follow the
|
|
901
|
+
// leader's status" (b80a14d) still painted the whole block red whenever
|
|
902
|
+
// the first call itself was the one that failed. Pending does
|
|
903
|
+
// aggregate: the box stays in its running state until every call in
|
|
904
|
+
// the burst has landed.
|
|
905
|
+
const pending = isGrouped
|
|
906
|
+
? burst.entries.some((e) => !e.result)
|
|
907
|
+
: !entry.result;
|
|
908
|
+
const isError = isGrouped ? false : !!entry.isError;
|
|
884
909
|
|
|
885
910
|
if (isGrouped && !isLeader) {
|
|
886
911
|
// Refresh the leader's header/count. Single hop: a leader's renderCall
|