@ikyyofc/gemini-cli 1.0.3 → 1.0.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/package.json +1 -1
- package/src/agent.js +18 -42
- package/src/renderer.js +227 -85
package/package.json
CHANGED
package/src/agent.js
CHANGED
|
@@ -3,7 +3,7 @@ import chalk from "chalk";
|
|
|
3
3
|
import ora from "ora";
|
|
4
4
|
import { callGemini } from "./gemini.js";
|
|
5
5
|
import { GEMINI_TOOLS, executeTool } from "./tools.js";
|
|
6
|
-
import { printAssistant, printError, printWarning } from "./renderer.js";
|
|
6
|
+
import { printAssistant, printError, printWarning, printToolCall, printToolResult } from "./renderer.js";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Run the agent loop until the model gives a final text answer (no more tool calls).
|
|
@@ -68,15 +68,28 @@ export async function runAgentLoop(userMessage, history, {
|
|
|
68
68
|
// ── No tool calls → final answer ────────────────────────
|
|
69
69
|
if (callParts.length === 0) {
|
|
70
70
|
const final = textParts.map(p => p.text).join("").trim();
|
|
71
|
+
// Close the tool section if it was opened
|
|
72
|
+
if (iteration > 1) {
|
|
73
|
+
process.stdout.write(
|
|
74
|
+
chalk.hex("#4A9EFF")(" ╰") +
|
|
75
|
+
chalk.hex("#555566")("─".repeat(47)) + "\n"
|
|
76
|
+
);
|
|
77
|
+
}
|
|
71
78
|
if (final) printAssistant(final);
|
|
72
79
|
return { finalResponse: final, iterations: iteration };
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
// ── Execute each tool call ───────────────────────────────
|
|
76
|
-
// Append the model's turn (contains functionCall parts) to history
|
|
77
83
|
messages.push({ role: "model", parts });
|
|
78
84
|
|
|
79
|
-
//
|
|
85
|
+
// Print tool section header on first iteration
|
|
86
|
+
if (iteration === 1) {
|
|
87
|
+
process.stdout.write(
|
|
88
|
+
"\n" + chalk.hex("#4A9EFF")(" ╭─ working") +
|
|
89
|
+
chalk.hex("#555566")(" " + "─".repeat(36)) + "\n"
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
80
93
|
const responseParts = [];
|
|
81
94
|
|
|
82
95
|
for (const part of callParts) {
|
|
@@ -84,17 +97,13 @@ export async function runAgentLoop(userMessage, history, {
|
|
|
84
97
|
printToolCall(name, args);
|
|
85
98
|
|
|
86
99
|
const result = await executeTool(name, args ?? {}, { autoApprove });
|
|
87
|
-
printToolResult(result
|
|
100
|
+
printToolResult(result);
|
|
88
101
|
|
|
89
102
|
responseParts.push({
|
|
90
|
-
functionResponse: {
|
|
91
|
-
name,
|
|
92
|
-
response: result // the entire result object goes here
|
|
93
|
-
}
|
|
103
|
+
functionResponse: { name, response: result }
|
|
94
104
|
});
|
|
95
105
|
}
|
|
96
106
|
|
|
97
|
-
// Append user turn with all function responses
|
|
98
107
|
messages.push({ role: "user", parts: responseParts });
|
|
99
108
|
}
|
|
100
109
|
|
|
@@ -102,39 +111,6 @@ export async function runAgentLoop(userMessage, history, {
|
|
|
102
111
|
return { finalResponse: null, iterations: iteration };
|
|
103
112
|
}
|
|
104
113
|
|
|
105
|
-
// ─────────────────────────────────────────────────────────────────
|
|
106
|
-
// Terminal rendering helpers for tool calls
|
|
107
|
-
// ─────────────────────────────────────────────────────────────────
|
|
108
|
-
function printToolCall(name, args = {}) {
|
|
109
|
-
const preview = Object.entries(args)
|
|
110
|
-
.map(([k, v]) => {
|
|
111
|
-
const s = String(v);
|
|
112
|
-
return chalk.dim(k + ":") + (s.length > 60 ? s.slice(0, 60) + "…" : s);
|
|
113
|
-
})
|
|
114
|
-
.join(" ");
|
|
115
|
-
|
|
116
|
-
process.stdout.write(
|
|
117
|
-
" " + chalk.dim("run") + " " +
|
|
118
|
-
chalk.hex("#569CD6")(name) +
|
|
119
|
-
(preview ? chalk.dim(" " + preview) : "") + "\n"
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function printToolResult(result, name) {
|
|
124
|
-
const text = typeof result === "object"
|
|
125
|
-
? (result.result ?? result.error ?? JSON.stringify(result))
|
|
126
|
-
: String(result);
|
|
127
|
-
const isErr = typeof result === "object" && result.error;
|
|
128
|
-
const color = isErr ? chalk.red : chalk.dim;
|
|
129
|
-
const lines = text.split("\n").slice(0, 12);
|
|
130
|
-
const more = text.split("\n").length > 12
|
|
131
|
-
? chalk.dim(`\n … +${text.split("\n").length - 12} lines`) : "";
|
|
132
|
-
|
|
133
|
-
process.stdout.write(
|
|
134
|
-
" " + color(lines.join("\n ")) + more + "\n"
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
114
|
function clearLine() {
|
|
139
115
|
if (process.stdout.clearLine) { process.stdout.clearLine(0); process.stdout.cursorTo(0); }
|
|
140
116
|
}
|
package/src/renderer.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
// src/renderer.js
|
|
1
|
+
// src/renderer.js
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
|
|
4
|
+
// Accent colors
|
|
5
|
+
const C = {
|
|
6
|
+
blue: "#4A9EFF",
|
|
7
|
+
teal: "#1DB8A0",
|
|
8
|
+
dim: "#555566",
|
|
9
|
+
code: "#CE9178",
|
|
10
|
+
kw: "#569CD6",
|
|
11
|
+
str: "#CE9178",
|
|
12
|
+
comment: "#6A9955",
|
|
13
|
+
num: "#B5CEA8",
|
|
14
|
+
fn: "#DCDCAA",
|
|
15
|
+
green: "#4EC9B0",
|
|
16
|
+
yellow: "#E5C07B",
|
|
17
|
+
red: "#E06C75",
|
|
18
|
+
white: "#CDD6F4",
|
|
19
|
+
};
|
|
20
|
+
|
|
4
21
|
// ─────────────────────────────────────────────────────────────────
|
|
5
22
|
// Syntax highlighting
|
|
6
23
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -9,13 +26,13 @@ const KW = {
|
|
|
9
26
|
ts: /\b(const|let|var|function|return|if|else|for|while|switch|case|class|extends|import|export|default|async|await|try|catch|type|interface|enum|implements|declare|readonly|abstract|as|keyof|never|any|string|number|boolean|null|undefined|true|false)\b/g,
|
|
10
27
|
py: /\b(def|class|return|if|elif|else|for|while|import|from|as|with|try|except|finally|raise|pass|break|continue|and|or|not|in|is|None|True|False|lambda|yield|global|async|await)\b/g,
|
|
11
28
|
go: /\b(func|return|if|else|for|range|switch|var|const|type|struct|interface|import|package|defer|go|chan|map|make|new|nil|true|false)\b/g,
|
|
12
|
-
sh: /\b(if|then|else|elif|fi|for|while|do|done|case|esac|function|return|exit|export|echo|local|source)\b/g,
|
|
29
|
+
sh: /\b(if|then|else|elif|fi|for|while|do|done|case|esac|function|return|exit|export|echo|local|source|cd|mkdir|rm|cp|mv)\b/g,
|
|
13
30
|
rs: /\b(fn|let|mut|return|if|else|for|match|use|mod|pub|struct|enum|impl|trait|type|const|async|await|true|false|None|Some|Ok|Err)\b/g,
|
|
14
31
|
};
|
|
15
32
|
const LANGMAP = {
|
|
16
33
|
javascript:"js",js:"js",typescript:"ts",ts:"ts",
|
|
17
34
|
python:"py",py:"py",go:"go",golang:"go",
|
|
18
|
-
rust:"rs",rs:"rs",bash:"sh",sh:"sh",shell:"sh",zsh:"sh"
|
|
35
|
+
rust:"rs",rs:"rs",bash:"sh",sh:"sh",shell:"sh",zsh:"sh",fish:"sh",
|
|
19
36
|
};
|
|
20
37
|
|
|
21
38
|
function highlight(code, lang = "") {
|
|
@@ -24,11 +41,11 @@ function highlight(code, lang = "") {
|
|
|
24
41
|
const saved = [];
|
|
25
42
|
const save = s => { const id = `\x00${saved.length}\x00`; saved.push(s); return id; };
|
|
26
43
|
|
|
27
|
-
r = r.replace(/(\/\/.*$|#.*$|\/\*[\s\S]*?\*\/)/gm,
|
|
28
|
-
r = r.replace(/("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`)/g, m => save(chalk.hex(
|
|
29
|
-
if (KW[l]) r = r.replace(KW[l], m => save(chalk.hex(
|
|
30
|
-
r = r.replace(/\b(\d+\.?\d*)\b/g, m => save(chalk.hex(
|
|
31
|
-
r = r.replace(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?=\()/g, m => save(chalk.hex(
|
|
44
|
+
r = r.replace(/(\/\/.*$|#.*$|\/\*[\s\S]*?\*\/)/gm, m => save(chalk.hex(C.comment).italic(m)));
|
|
45
|
+
r = r.replace(/("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`)/g, m => save(chalk.hex(C.str)(m)));
|
|
46
|
+
if (KW[l]) r = r.replace(KW[l], m => save(chalk.hex(C.kw).bold(m)));
|
|
47
|
+
r = r.replace(/\b(\d+\.?\d*)\b/g, m => save(chalk.hex(C.num)(m)));
|
|
48
|
+
r = r.replace(/\b([a-zA-Z_$][a-zA-Z0-9_$]*)\s*(?=\()/g, m => save(chalk.hex(C.fn)(m)));
|
|
32
49
|
return r.replace(/\x00(\d+)\x00/g, (_, i) => saved[parseInt(i)]);
|
|
33
50
|
}
|
|
34
51
|
|
|
@@ -38,22 +55,46 @@ function highlight(code, lang = "") {
|
|
|
38
55
|
export function renderMarkdown(text) {
|
|
39
56
|
let r = text;
|
|
40
57
|
|
|
41
|
-
// Fenced code blocks
|
|
58
|
+
// Fenced code blocks — with line gutter
|
|
42
59
|
r = r.replace(/```(\w*)\n?([\s\S]*?)```/g, (_, lang, code) => {
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
60
|
+
const trimmed = code.trimEnd();
|
|
61
|
+
const lines = trimmed.split("\n");
|
|
62
|
+
const hl = highlight(trimmed, lang);
|
|
63
|
+
const hlLines = hl.split("\n");
|
|
64
|
+
const lbl = lang
|
|
65
|
+
? chalk.hex(C.blue).bold(` ${lang} `)
|
|
66
|
+
: "";
|
|
67
|
+
const gutterW = String(lines.length).length;
|
|
68
|
+
|
|
69
|
+
const header = chalk.hex(C.dim)(" ╭") +
|
|
70
|
+
chalk.hex(C.dim)("─".repeat(2)) +
|
|
71
|
+
lbl +
|
|
72
|
+
chalk.hex(C.dim)("─".repeat(Math.max(0, 40 - lang.length - 2))) +
|
|
73
|
+
"╮";
|
|
74
|
+
const footer = chalk.hex(C.dim)(" ╰" + "─".repeat(44) + "╯");
|
|
75
|
+
const body = hlLines.map((l, i) => {
|
|
76
|
+
const n = chalk.hex(C.dim)(String(i + 1).padStart(gutterW));
|
|
77
|
+
return chalk.hex(C.dim)(" │ ") + n + chalk.hex(C.dim)(" │ ") + l;
|
|
78
|
+
}).join("\n");
|
|
79
|
+
|
|
80
|
+
return `\n${header}\n${body}\n${footer}\n`;
|
|
48
81
|
});
|
|
49
82
|
|
|
50
83
|
// Inline code
|
|
51
|
-
r = r.replace(/`([^`\n]+)`/g, (_, c) =>
|
|
84
|
+
r = r.replace(/`([^`\n]+)`/g, (_, c) =>
|
|
85
|
+
chalk.hex(C.code)("‹") + chalk.hex(C.code).bold(c) + chalk.hex(C.code)("›")
|
|
86
|
+
);
|
|
52
87
|
|
|
53
88
|
// Headers
|
|
54
|
-
r = r.replace(/^### (.+)$/gm, (_, t) =>
|
|
55
|
-
|
|
56
|
-
|
|
89
|
+
r = r.replace(/^### (.+)$/gm, (_, t) =>
|
|
90
|
+
"\n" + chalk.hex(C.yellow).bold(" › " + t)
|
|
91
|
+
);
|
|
92
|
+
r = r.replace(/^## (.+)$/gm, (_, t) =>
|
|
93
|
+
"\n" + chalk.hex(C.blue).bold(" ›› " + t)
|
|
94
|
+
);
|
|
95
|
+
r = r.replace(/^# (.+)$/gm, (_, t) =>
|
|
96
|
+
"\n" + chalk.hex(C.teal).bold(" ▸ " + t.toUpperCase())
|
|
97
|
+
);
|
|
57
98
|
|
|
58
99
|
// Bold / italic
|
|
59
100
|
r = r.replace(/\*\*\*(.+?)\*\*\*/g, (_, t) => chalk.bold.italic(t));
|
|
@@ -61,124 +102,225 @@ export function renderMarkdown(text) {
|
|
|
61
102
|
r = r.replace(/\*(.+?)\*/g, (_, t) => chalk.italic(t));
|
|
62
103
|
|
|
63
104
|
// Blockquotes
|
|
64
|
-
r = r.replace(/^> (.+)$/gm, (_, t) =>
|
|
105
|
+
r = r.replace(/^> (.+)$/gm, (_, t) =>
|
|
106
|
+
chalk.hex(C.blue)(" ▌ ") + chalk.hex(C.white).italic(t)
|
|
107
|
+
);
|
|
65
108
|
|
|
66
109
|
// Lists
|
|
67
|
-
r = r.replace(/^(\s*)[*\-+] (.+)$/gm,
|
|
68
|
-
|
|
110
|
+
r = r.replace(/^(\s*)[*\-+] (.+)$/gm, (_, ind, t) =>
|
|
111
|
+
ind + chalk.hex(C.teal)(" ◆ ") + t
|
|
112
|
+
);
|
|
113
|
+
r = r.replace(/^(\s*)(\d+)\. (.+)$/gm, (_, ind, n, t) =>
|
|
114
|
+
ind + chalk.hex(C.blue)(" " + n + ". ") + t
|
|
115
|
+
);
|
|
69
116
|
|
|
70
117
|
// HR
|
|
71
|
-
r = r.replace(/^---+$/gm,
|
|
118
|
+
r = r.replace(/^---+$/gm,
|
|
119
|
+
chalk.hex(C.dim)(" " + "─".repeat(50))
|
|
120
|
+
);
|
|
72
121
|
|
|
73
122
|
return r;
|
|
74
123
|
}
|
|
75
124
|
|
|
76
125
|
// ─────────────────────────────────────────────────────────────────
|
|
77
|
-
// Message printers
|
|
126
|
+
// Message printers
|
|
78
127
|
// ─────────────────────────────────────────────────────────────────
|
|
79
128
|
export function printUser(text) {
|
|
80
|
-
// Show multi-line messages cleanly
|
|
81
129
|
const lines = text.split("\n");
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
process.stdout.write(
|
|
87
|
-
|
|
130
|
+
const isMulti = lines.length > 1;
|
|
131
|
+
|
|
132
|
+
// Single line: compact
|
|
133
|
+
if (!isMulti) {
|
|
134
|
+
process.stdout.write(
|
|
135
|
+
"\n" +
|
|
136
|
+
chalk.hex(C.blue)(" ╸ ") +
|
|
137
|
+
chalk.hex(C.blue).bold("you ") +
|
|
138
|
+
chalk.hex(C.white)(text) +
|
|
139
|
+
"\n"
|
|
140
|
+
);
|
|
141
|
+
return;
|
|
88
142
|
}
|
|
143
|
+
|
|
144
|
+
// Multi-line (pasted code): show with left bar
|
|
145
|
+
process.stdout.write(
|
|
146
|
+
"\n" +
|
|
147
|
+
chalk.hex(C.blue)(" ╸ ") +
|
|
148
|
+
chalk.hex(C.blue).bold("you") +
|
|
149
|
+
chalk.hex(C.dim)(` (${lines.length} lines)`) +
|
|
150
|
+
"\n"
|
|
151
|
+
);
|
|
152
|
+
lines.forEach(l =>
|
|
153
|
+
process.stdout.write(chalk.hex(C.blue)(" │ ") + chalk.hex(C.white)(l) + "\n")
|
|
154
|
+
);
|
|
155
|
+
process.stdout.write(chalk.hex(C.blue)(" ╹") + "\n");
|
|
89
156
|
}
|
|
90
157
|
|
|
91
158
|
export function printAssistant(text) {
|
|
92
|
-
const
|
|
93
|
-
const lines
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
159
|
+
const rendered = renderMarkdown(text);
|
|
160
|
+
const lines = rendered.split("\n");
|
|
161
|
+
|
|
162
|
+
process.stdout.write(
|
|
163
|
+
"\n" +
|
|
164
|
+
chalk.hex(C.teal)(" ╸ ") +
|
|
165
|
+
chalk.hex(C.teal).bold("gemini") +
|
|
166
|
+
"\n"
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
lines.forEach(l =>
|
|
170
|
+
process.stdout.write(chalk.hex(C.teal)(" │ ") + l + "\n")
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
process.stdout.write(chalk.hex(C.teal)(" ╹") + "\n\n");
|
|
100
174
|
}
|
|
101
175
|
|
|
176
|
+
// ─────────────────────────────────────────────────────────────────
|
|
177
|
+
// Status messages
|
|
178
|
+
// ─────────────────────────────────────────────────────────────────
|
|
102
179
|
export function printError(msg) {
|
|
103
|
-
process.stdout.write(
|
|
180
|
+
process.stdout.write(
|
|
181
|
+
"\n" +
|
|
182
|
+
chalk.hex(C.red)(" ✗ ") +
|
|
183
|
+
chalk.hex(C.red).bold("error ") +
|
|
184
|
+
chalk.white(msg) +
|
|
185
|
+
"\n\n"
|
|
186
|
+
);
|
|
104
187
|
}
|
|
105
188
|
export function printInfo(msg) {
|
|
106
|
-
process.stdout.write(
|
|
189
|
+
process.stdout.write(
|
|
190
|
+
chalk.hex(C.dim)(" · ") +
|
|
191
|
+
chalk.hex(C.white)(msg) +
|
|
192
|
+
"\n"
|
|
193
|
+
);
|
|
107
194
|
}
|
|
108
195
|
export function printSuccess(msg) {
|
|
109
|
-
process.stdout.write(
|
|
196
|
+
process.stdout.write(
|
|
197
|
+
chalk.hex(C.teal)(" ✓ ") +
|
|
198
|
+
chalk.hex(C.teal)(msg) +
|
|
199
|
+
"\n"
|
|
200
|
+
);
|
|
110
201
|
}
|
|
111
202
|
export function printWarning(msg) {
|
|
112
|
-
process.stdout.write(
|
|
203
|
+
process.stdout.write(
|
|
204
|
+
chalk.hex(C.yellow)(" ⚠ ") +
|
|
205
|
+
chalk.hex(C.yellow)(msg) +
|
|
206
|
+
"\n"
|
|
207
|
+
);
|
|
113
208
|
}
|
|
114
209
|
|
|
115
210
|
// ─────────────────────────────────────────────────────────────────
|
|
116
|
-
//
|
|
211
|
+
// Tool call display (used by agent.js)
|
|
212
|
+
// ─────────────────────────────────────────────────────────────────
|
|
213
|
+
export function printToolCall(name, args = {}) {
|
|
214
|
+
const argStr = Object.entries(args)
|
|
215
|
+
.map(([k, v]) => {
|
|
216
|
+
const s = String(v);
|
|
217
|
+
return chalk.hex(C.dim)(k + ":") + chalk.hex(C.code)(s.length > 55 ? s.slice(0, 55) + "…" : s);
|
|
218
|
+
})
|
|
219
|
+
.join(" ");
|
|
220
|
+
|
|
221
|
+
process.stdout.write(
|
|
222
|
+
chalk.hex(C.blue)(" ├─ ") +
|
|
223
|
+
chalk.hex(C.blue).bold(name) +
|
|
224
|
+
(argStr ? " " + argStr : "") +
|
|
225
|
+
"\n"
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function printToolResult(result) {
|
|
230
|
+
const isErr = typeof result === "object" && result.error;
|
|
231
|
+
const text = typeof result === "object"
|
|
232
|
+
? (result.result ?? result.error ?? JSON.stringify(result))
|
|
233
|
+
: String(result);
|
|
234
|
+
const color = isErr ? chalk.hex(C.red) : chalk.hex(C.dim);
|
|
235
|
+
const lines = text.split("\n");
|
|
236
|
+
const shown = lines.slice(0, 10);
|
|
237
|
+
const extra = lines.length > 10 ? chalk.hex(C.dim)(` +${lines.length - 10} more lines`) : "";
|
|
238
|
+
|
|
239
|
+
shown.forEach(l =>
|
|
240
|
+
process.stdout.write(chalk.hex(C.dim)(" │ ") + color(l) + "\n")
|
|
241
|
+
);
|
|
242
|
+
if (extra) process.stdout.write(" " + extra + "\n");
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ─────────────────────────────────────────────────────────────────
|
|
246
|
+
// Welcome screen
|
|
117
247
|
// ─────────────────────────────────────────────────────────────────
|
|
118
248
|
export function renderWelcome(memCount = 0, extCount = 0) {
|
|
119
249
|
const stats = [
|
|
120
|
-
memCount
|
|
121
|
-
extCount
|
|
122
|
-
].filter(Boolean)
|
|
250
|
+
memCount ? `${memCount} context file${memCount > 1 ? "s" : ""}` : null,
|
|
251
|
+
extCount ? `${extCount} extension${extCount > 1 ? "s" : ""}` : null,
|
|
252
|
+
].filter(Boolean);
|
|
253
|
+
|
|
254
|
+
const sep = chalk.hex(C.blue)(" " + "━".repeat(46));
|
|
123
255
|
|
|
124
256
|
return [
|
|
125
257
|
"",
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
258
|
+
sep,
|
|
259
|
+
chalk.hex(C.teal).bold(" Gemini CLI") +
|
|
260
|
+
chalk.hex(C.dim)(" ─ AI Agent ─ native function calling"),
|
|
261
|
+
sep,
|
|
262
|
+
stats.length
|
|
263
|
+
? chalk.hex(C.dim)(" ") + chalk.hex(C.white)(stats.join(" · "))
|
|
264
|
+
: "",
|
|
265
|
+
chalk.hex(C.dim)(" /help") +
|
|
266
|
+
chalk.hex(C.dim)(" for commands · ") +
|
|
267
|
+
chalk.hex(C.dim)("/agent") +
|
|
268
|
+
chalk.hex(C.dim)(" to toggle tools"),
|
|
130
269
|
"",
|
|
131
270
|
].join("\n");
|
|
132
271
|
}
|
|
133
272
|
|
|
134
273
|
// ─────────────────────────────────────────────────────────────────
|
|
135
|
-
// Help
|
|
274
|
+
// Help screen
|
|
136
275
|
// ─────────────────────────────────────────────────────────────────
|
|
137
276
|
export function renderHelp(customCommands = {}) {
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
),
|
|
145
|
-
].join("\n");
|
|
277
|
+
const sep = chalk.hex(C.dim)(" " + "─".repeat(50));
|
|
278
|
+
|
|
279
|
+
const row = (cmd, desc) =>
|
|
280
|
+
" " +
|
|
281
|
+
chalk.hex(C.blue).bold(cmd.padEnd(28)) +
|
|
282
|
+
chalk.hex(C.dim)(desc);
|
|
146
283
|
|
|
147
284
|
const lines = [
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
285
|
+
"",
|
|
286
|
+
chalk.hex(C.teal).bold(" Commands"),
|
|
287
|
+
sep,
|
|
288
|
+
row("/agent", "Toggle agent mode (tools on/off)"),
|
|
289
|
+
row("/yolo", "Skip all tool confirmations"),
|
|
290
|
+
sep,
|
|
291
|
+
row("/memory show", "Show loaded GEMINI.md files"),
|
|
292
|
+
row("/memory reload", "Reload context from disk"),
|
|
293
|
+
row("/memory add <text>", "Append to ~/.gemini/GEMINI.md"),
|
|
294
|
+
sep,
|
|
295
|
+
row("/ext list", "List installed extensions"),
|
|
296
|
+
row("/ext install <src>", "Install from path or git URL"),
|
|
297
|
+
row("/ext uninstall <n>", "Remove extension"),
|
|
298
|
+
row("/ext enable <n>", "Enable extension"),
|
|
299
|
+
row("/ext disable <n>", "Disable extension"),
|
|
300
|
+
row("/ext update <n>", "Pull latest from git"),
|
|
301
|
+
sep,
|
|
302
|
+
row("/file <path>", "Attach file to next message"),
|
|
303
|
+
row("/system <text>", "Set system instruction"),
|
|
304
|
+
row("/history", "Show conversation turns"),
|
|
305
|
+
row("/export <file>", "Export history to JSON"),
|
|
306
|
+
row("/cd <path>", "Change working directory"),
|
|
307
|
+
row("/new /clear", "Reset conversation"),
|
|
308
|
+
row("/model", "Show model & config"),
|
|
309
|
+
row("/exit /quit", "Exit"),
|
|
168
310
|
];
|
|
169
311
|
|
|
170
312
|
const cmds = Object.entries(customCommands);
|
|
171
313
|
if (cmds.length) {
|
|
172
|
-
lines.push(
|
|
173
|
-
|
|
174
|
-
));
|
|
314
|
+
lines.push("", chalk.hex(C.teal).bold(" Extension Commands"), sep);
|
|
315
|
+
cmds.forEach(([k, c]) => lines.push(row("/" + k, c.description ?? "")));
|
|
175
316
|
}
|
|
176
317
|
|
|
177
318
|
lines.push(
|
|
178
319
|
"",
|
|
179
|
-
chalk.dim(" Paste multi-line code freely —
|
|
180
|
-
chalk.dim(" Ctrl+C
|
|
181
|
-
""
|
|
320
|
+
chalk.hex(C.dim)(" Paste multi-line code freely — collected as one input."),
|
|
321
|
+
chalk.hex(C.dim)(" Ctrl+C cancel/exit · Ctrl+D exit"),
|
|
322
|
+
"",
|
|
182
323
|
);
|
|
324
|
+
|
|
183
325
|
return lines.join("\n");
|
|
184
326
|
}
|