@tiens.nguyen/gu-cli 1.0.808 → 1.0.810
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/gu-repl.mjs +13 -8
- package/package.json +1 -1
- package/terminal-layout.mjs +42 -0
package/gu-repl.mjs
CHANGED
|
@@ -142,7 +142,7 @@ import { unapprovedProjectServers } from "./mcp-command.mjs";
|
|
|
142
142
|
import { readHooks } from "./hooks-config.mjs";
|
|
143
143
|
import { readSkillSource, sourceLabel, SKILL_SOURCE_KEY } from "./skill-source.mjs";
|
|
144
144
|
import { codingBannerLabel, isOllamaCloudUrl, SECRET_KEY_HINT } from "./coding-key-prompt.mjs";
|
|
145
|
-
import { questionEchoText, thoughtPrintSeq } from "./terminal-layout.mjs";
|
|
145
|
+
import { questionEchoText, thoughtPrintSeq, wrapDiffText } from "./terminal-layout.mjs";
|
|
146
146
|
import { globalPrefixOf } from "./install-path.mjs";
|
|
147
147
|
import { firstGuOnPath, pathGuMismatch, guOnPathIsCurrent, updateAttemptRecord, repeatUpdateNotice } from "./update-verify.mjs";
|
|
148
148
|
import { embedNotice, embedState } from "./embed-model-command.mjs";
|
|
@@ -917,16 +917,14 @@ const COMMANDS = [
|
|
|
917
917
|
// outside, it is confused". The command still works and still does the same thing.
|
|
918
918
|
{ name: "/agent-model", desc: "switch the AGENT model (the one that talks) — saved on this machine" },
|
|
919
919
|
{ name: "/embed-model", desc: "switch the RAG EMBEDDING model (nomic-embed-text / qwen3-embedding) and its server — re-indexes what is already indexed; supports a remote URL + API key" },
|
|
920
|
-
|
|
921
|
-
//
|
|
922
|
-
//
|
|
923
|
-
// is what made this confusing in the first place.
|
|
924
|
-
{ name: "/rag", desc: "where this folder's RAG knowledge base lives: local, cloud, or both" },
|
|
920
|
+
// /test-auto is HIDDEN_COMMANDS now — the handler still works when typed, it is just not offered.
|
|
921
|
+
// /rag, /rag-local and /rag-cloud all still work — they are in people's fingers — but they are
|
|
922
|
+
// HIDDEN_COMMANDS now, so /help and Tab-completion do not offer them.
|
|
925
923
|
// The two synonyms were dispatched but declared nowhere (found by slash-command-wiring.test.mjs):
|
|
926
924
|
// they worked, Tab-completed to nothing, and appeared in no help. Aliases is what the registry
|
|
927
925
|
// already has for exactly this — /quit, /rag-local.
|
|
928
926
|
{ name: "/host-mode", desc: "undo client mode — run agent turns on THIS machine again" },
|
|
929
|
-
|
|
927
|
+
// /undo is HIDDEN_COMMANDS now — still works when typed.
|
|
930
928
|
{ name: "/server", desc: "pick a deployment server (host/user) for this session" },
|
|
931
929
|
{ name: "/proxy", usage: "/proxy [show|set|on|off|clear|test]", desc: "route MODEL calls through an HTTP proxy (local calls always go direct)" },
|
|
932
930
|
{ name: "/s3", usage: "/s3 [test]", desc: "set up YOUR S3 bucket (RAG index, and the PDFs/downloads gu makes) and check the AWS keys work — without it, files are saved on this computer" },
|
|
@@ -12053,7 +12051,14 @@ async function runAgentTurn(history, { attachJobId = "", ownJob = false } = {})
|
|
|
12053
12051
|
if (m) {
|
|
12054
12052
|
// " 19 - old text" → dim line number, red/cyan signed content.
|
|
12055
12053
|
const paintDiff = m[3] === "+" ? accent : red;
|
|
12056
|
-
|
|
12054
|
+
// Wrap to the terminal width: continuation rows hang under the text column
|
|
12055
|
+
// (no line number, blank sign) instead of soft-wrapping back to column 0.
|
|
12056
|
+
const room = Math.max(8, Math.max(20, process.stdout.columns || 80) - 1 - visibleLen(GUTTER) - m[1].length - m[2].length - 1 - 2);
|
|
12057
|
+
const pieces = wrapDiffText(m[4], room);
|
|
12058
|
+
process.stdout.write(`${GUTTER}${m[1]}${dim(m[2])} ${paintDiff(`${m[3]} ${pieces[0]}`)}\n`);
|
|
12059
|
+
for (const p of pieces.slice(1)) {
|
|
12060
|
+
process.stdout.write(`${GUTTER}${m[1]}${" ".repeat(m[2].length)} ${paintDiff(` ${p}`)}\n`);
|
|
12061
|
+
}
|
|
12057
12062
|
} else {
|
|
12058
12063
|
process.stdout.write(GUTTER + dim(line) + "\n"); // "└ summary" / "… (+N more)"
|
|
12059
12064
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiens.nguyen/gu-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.810",
|
|
4
4
|
"description": "Gu CLI — the gu terminal plus the local worker that runs agent / OCR / PDF / embedding jobs on your Mac (Ollama / MLX / OpenAI-compatible).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/terminal-layout.mjs
CHANGED
|
@@ -66,6 +66,45 @@ export function clipVisible(s, max) {
|
|
|
66
66
|
return out;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Wrap the TEXT of one edit-card diff row so no piece is wider than `room` visible columns
|
|
71
|
+
* (task #24). A raw over-wide row is soft-wrapped by the terminal back to column 0, which
|
|
72
|
+
* destroys the card's indent. Prefers breaking after a space; a token longer than a whole
|
|
73
|
+
* row is hard-split. The caller paints the first piece after the line number and every
|
|
74
|
+
* further piece under the text column (hanging indent). Leading code indentation is kept.
|
|
75
|
+
*/
|
|
76
|
+
export function wrapDiffText(text, room) {
|
|
77
|
+
const max = Math.max(8, Math.floor(room) || 8);
|
|
78
|
+
const chars = [...String(text ?? "").replace(/\t/g, " ")];
|
|
79
|
+
const rows = [];
|
|
80
|
+
let cur = [];
|
|
81
|
+
let w = 0;
|
|
82
|
+
let lastSpace = -1;
|
|
83
|
+
for (const ch of chars) {
|
|
84
|
+
const cw = charWidth(ch);
|
|
85
|
+
if (w + cw > max) {
|
|
86
|
+
const canBreak = lastSpace > 0 && ch !== " " && cur.slice(0, lastSpace).some((c) => c !== " ");
|
|
87
|
+
if (canBreak) {
|
|
88
|
+
const tail = cur.slice(lastSpace + 1);
|
|
89
|
+
rows.push(cur.slice(0, lastSpace).join("").replace(/\s+$/, ""));
|
|
90
|
+
cur = tail;
|
|
91
|
+
w = tail.reduce((n, c) => n + charWidth(c), 0);
|
|
92
|
+
} else {
|
|
93
|
+
rows.push(cur.join(""));
|
|
94
|
+
cur = [];
|
|
95
|
+
w = 0;
|
|
96
|
+
}
|
|
97
|
+
lastSpace = -1;
|
|
98
|
+
if (ch === " ") continue; // a space that lands on the break is not carried to the next row
|
|
99
|
+
}
|
|
100
|
+
cur.push(ch);
|
|
101
|
+
w += cw;
|
|
102
|
+
if (ch === " ") lastSpace = cur.length - 1;
|
|
103
|
+
}
|
|
104
|
+
rows.push(cur.join(""));
|
|
105
|
+
return rows;
|
|
106
|
+
}
|
|
107
|
+
|
|
69
108
|
/**
|
|
70
109
|
* The prompt breakdown as rows to print (task #142) — WHERE the coding model's context went.
|
|
71
110
|
*
|
|
@@ -2296,6 +2335,9 @@ export const HIDDEN_COMMANDS = [
|
|
|
2296
2335
|
// too offered two doors into one setting (reported as confusing)
|
|
2297
2336
|
"/rag-local", // superseded by /rag's picker; still work, still mean what
|
|
2298
2337
|
"/rag-cloud", // they say — unlisted so /help offers one way into the setting
|
|
2338
|
+
"/rag", // hidden too (user request, #25): handler unchanged, not offered
|
|
2339
|
+
"/test-auto", // hidden, still toggles auto-test when typed
|
|
2340
|
+
"/undo", // hidden, still restores the last stopped turn when typed
|
|
2299
2341
|
"/thought", // the reasoning display stays ON; only the toggle is unlisted
|
|
2300
2342
|
"/hover", // in-turn mouse capture — behaviour unchanged, just hidden
|
|
2301
2343
|
"/reset", // the old name of /new (#278) — still works, one name is offered
|