@tiens.nguyen/gu-cli 1.0.835 → 1.0.836
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_agent_chat.py +277 -35
- package/gu-cli.mjs +34 -3
- package/gu-repl.mjs +71 -16
- package/gu_powershell.py +675 -0
- package/install-path.mjs +19 -2
- package/package.json +3 -1
- package/shell-details.mjs +55 -20
- package/win-path.mjs +185 -0
package/gu-repl.mjs
CHANGED
|
@@ -140,7 +140,7 @@ import { completedFlush, splitLiveStream } from "./completed-flush.mjs";
|
|
|
140
140
|
import { isScaffoldStep, isGroupableStep, stepGroupRows, relativizePaths } from "./step-group.mjs";
|
|
141
141
|
import { clearLogsNoticeText } from "./clear-logs.mjs";
|
|
142
142
|
import { allowIn, allowedIn, bridgeCommand, browserReport, bridgeStatus, extensionDir, findDevInstalls, helpInstall, installExtensionFiles, installSteps, localLeftovers, openExtensionsPage, removeLocalFiles, STORE_URL, stopBridge } from "./browser-command.mjs";
|
|
143
|
-
import { commandLogFile, killShell, logTail, markAnnounced, readShells, recapQuestion, shellsToRecap, statusText as shellStatusText, renderShellDetails, shellPickerLabel, shellState, shellsNotice } from "./shell-details.mjs";
|
|
143
|
+
import { commandLogFile, killShell, logTail, markAnnounced, readShells, recapQuestion, shellsToRecap, statusText as shellStatusText, renderShellDetails, shellPanelRows, shellPickerLabel, shellState, shellsNotice } from "./shell-details.mjs";
|
|
144
144
|
import { discoverSkills, matchSkillCommand } from "./skills.mjs";
|
|
145
145
|
import { appendNew, archivePathFor, archivedWorkspaceKey, markReset, seedArchive } from "./conversation-archive.mjs";
|
|
146
146
|
import { addAllowRule, listServers as listMcpServers } from "./mcp-config.mjs";
|
|
@@ -9668,20 +9668,49 @@ async function showShells() {
|
|
|
9668
9668
|
}
|
|
9669
9669
|
}
|
|
9670
9670
|
const rec = entries[pick].rec;
|
|
9671
|
-
for
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9671
|
+
// During a turn a picker would fight the turn for the keyboard: the details are printed instead.
|
|
9672
|
+
if (following) {
|
|
9673
|
+
printShellDetails(rec);
|
|
9674
|
+
refreshShells();
|
|
9675
|
+
paintBar();
|
|
9676
|
+
return;
|
|
9677
|
+
}
|
|
9678
|
+
// AT THE BOTTOM, ABOVE THE BAR, LIVE; Esc closes (#376, GitHub #157) — Claude Code's Shell
|
|
9679
|
+
// details. Nothing goes into the scrollback: the panel and its choices are one block that the
|
|
9680
|
+
// picker wipes when it closes. Its height is fixed when it opens (what the screen allows, at most
|
|
9681
|
+
// the details plus 15 output lines) and it redraws once a second, so a build's runtime and
|
|
9682
|
+
// newest output move while you watch.
|
|
9683
|
+
shellsViewed.add(String(rec.id));
|
|
9684
|
+
const panel = (rowsWanted) => {
|
|
9685
|
+
const st = shellState(rec);
|
|
9686
|
+
let output = logTail(rec.log, { lines: 40 });
|
|
9687
|
+
let outputFrom = "";
|
|
9688
|
+
if (!output.length) {
|
|
9689
|
+
const lf = commandLogFile(rec.command, rec.workdir);
|
|
9690
|
+
if (lf) {
|
|
9691
|
+
output = logTail(lf, { lines: 40 });
|
|
9692
|
+
outputFrom = lf.startsWith(String(rec.workdir || "\0") + "/") ? lf.slice(String(rec.workdir).length + 1) : lf;
|
|
9693
|
+
}
|
|
9694
|
+
}
|
|
9695
|
+
return shellPanelRows({
|
|
9696
|
+
rec, st, output, outputFrom, width: Math.max(20, process.stdout.columns || 80) - 1, gutter: GUTTER, rows: rowsWanted,
|
|
9697
|
+
footer: "Esc to close",
|
|
9698
|
+
style: { title: (t) => bold(accent(t)), label: bold, running: accent, ok: accent, bad: red, dim },
|
|
9699
|
+
});
|
|
9700
|
+
};
|
|
9701
|
+
const running = shellState(rec).state === "running";
|
|
9702
|
+
const actions = running
|
|
9703
|
+
? [{ id: "kill", label: "Stop it", note: "kills the command and everything it started" }, { id: "close", label: "Close" }]
|
|
9704
|
+
: [{ id: "close", label: "Close" }];
|
|
9705
|
+
const headerRows = Math.max(8, Math.min(24, viewportHeight() - 3 - actions.length));
|
|
9706
|
+
const act = await pickFromList(
|
|
9707
|
+
actions.map((a) => a.label + (a.note ? dim(` · ${a.note}`) : "")),
|
|
9708
|
+
actions.length - 1, // Close: Enter on its own never stops a build
|
|
9709
|
+
{ header: panel, headerRows, refreshMs: 1000 },
|
|
9710
|
+
);
|
|
9711
|
+
if (act >= 0 && actions[act].id === "kill") {
|
|
9712
|
+
await killShell(rec);
|
|
9713
|
+
console.log(GUTTER + accent(`✓ stopped shell ${rec.id}`) + dim(" — the agent sees it as killed next turn.\n"));
|
|
9685
9714
|
}
|
|
9686
9715
|
refreshShells();
|
|
9687
9716
|
paintBar();
|
|
@@ -10795,6 +10824,12 @@ let listDeleteRequested = false;
|
|
|
10795
10824
|
// /use-presets' { o: "open" } (#312, #322). Null unless a caller asks, like ctrl+d above.
|
|
10796
10825
|
let listKeys = null;
|
|
10797
10826
|
let listKeyAction = "";
|
|
10827
|
+
// A PANEL ABOVE THE CHOICES (#376): `listHeader(rows)` returns exactly `listHeaderRows` rows, drawn
|
|
10828
|
+
// at the top of the same in-place block — Shell details sits at the bottom of the screen with its
|
|
10829
|
+
// actions under it, and goes with them (Esc) without leaving a line in the scrollback. A fixed
|
|
10830
|
+
// height, so the once-a-second redraw walks up the same rows it drew.
|
|
10831
|
+
let listHeader = null;
|
|
10832
|
+
let listHeaderRows = 0;
|
|
10798
10833
|
/** #321: the screen under a picker when it opened (content rows, pad, region height), and its tallest draw. */
|
|
10799
10834
|
let listOpenedOver = null;
|
|
10800
10835
|
let listMaxRows = 0;
|
|
@@ -10807,7 +10842,7 @@ function drawList(redraw) {
|
|
|
10807
10842
|
// provider's /v1/models was taller than the terminal: the screen scrolled, the highlighted row
|
|
10808
10843
|
// went off the top, and the ESC[nA walk below then counted rows that had moved — "cannot scroll
|
|
10809
10844
|
// up or down, stuck here". Two rows of margin keep the block clear of the line above it.
|
|
10810
|
-
const maxBlock = Math.max(5, viewportHeight() - 2) - (listNote ? 1 : 0);
|
|
10845
|
+
const maxBlock = Math.max(5, viewportHeight() - 2) - (listNote ? 1 : 0) - (listHeader ? listHeaderRows : 0);
|
|
10811
10846
|
const win = listWindow(listItems.length, listSel, listTop, maxBlock);
|
|
10812
10847
|
listTop = win.top;
|
|
10813
10848
|
const row = (i) => {
|
|
@@ -10821,6 +10856,11 @@ function drawList(redraw) {
|
|
|
10821
10856
|
};
|
|
10822
10857
|
const marker = (text) => clipVisible(GUTTER + dim(text), width - 1);
|
|
10823
10858
|
const rows = [];
|
|
10859
|
+
if (listHeader) {
|
|
10860
|
+
let head = [];
|
|
10861
|
+
try { head = listHeader(listHeaderRows) || []; } catch { /* a panel that fails to draw is blank */ }
|
|
10862
|
+
for (let i = 0; i < listHeaderRows; i++) rows.push(clipVisible(head[i] ?? "", width - 1));
|
|
10863
|
+
}
|
|
10824
10864
|
// Drawn even when empty, so the block keeps a CONSTANT height: every redraw walks up exactly as
|
|
10825
10865
|
// many rows as it drew, and a block that changed height at the ends would leave that walk out
|
|
10826
10866
|
// by a row — the bug physicalRows() exists to prevent.
|
|
@@ -10863,6 +10903,8 @@ function finishList(index) {
|
|
|
10863
10903
|
listMaxRows = 0;
|
|
10864
10904
|
listRowsDrawn = [];
|
|
10865
10905
|
listTop = 0;
|
|
10906
|
+
listHeader = null;
|
|
10907
|
+
listHeaderRows = 0;
|
|
10866
10908
|
const r = listResolve;
|
|
10867
10909
|
const multi = listMulti;
|
|
10868
10910
|
const checked = [...listChecked].sort((a, b) => a - b);
|
|
@@ -11007,6 +11049,19 @@ function pickFromList(items, initialSel = 0, opts = {}) {
|
|
|
11007
11049
|
listPickerActive = true;
|
|
11008
11050
|
listDeadline = 0;
|
|
11009
11051
|
listTimeoutIndex = -1;
|
|
11052
|
+
listHeader = typeof opts.header === "function" ? opts.header : null;
|
|
11053
|
+
listHeaderRows = listHeader ? Math.max(0, opts.headerRows | 0) : 0;
|
|
11054
|
+
if (listHeader && opts.refreshMs > 0) {
|
|
11055
|
+
// A live panel (#376): redrawn in place until the picker closes.
|
|
11056
|
+
const live = setInterval(() => {
|
|
11057
|
+
if (listPickerActive && listHeader) drawList(true);
|
|
11058
|
+
}, opts.refreshMs);
|
|
11059
|
+
const done = listResolve;
|
|
11060
|
+
listResolve = (v) => {
|
|
11061
|
+
clearInterval(live);
|
|
11062
|
+
done(v);
|
|
11063
|
+
};
|
|
11064
|
+
}
|
|
11010
11065
|
if (opts && opts.timeoutMs > 0 && (opts.timeoutIndex ?? -1) >= 0) {
|
|
11011
11066
|
listDeadline = Date.now() + opts.timeoutMs;
|
|
11012
11067
|
listTimeoutIndex = opts.timeoutIndex;
|