prab-cli 1.1.0 → 1.2.1
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/index.js +163 -3
- package/dist/lib/chat-handler.js +108 -23
- package/dist/lib/config.js +72 -13
- package/dist/lib/context.js +7 -12
- package/dist/lib/groq-models.js +3 -3
- package/dist/lib/groq.js +6 -6
- package/dist/lib/safety.js +29 -34
- package/dist/lib/slash-commands.js +6 -0
- package/dist/lib/tracker.js +74 -72
- package/dist/lib/ui.js +289 -109
- package/package.json +25 -3
package/dist/lib/ui.js
CHANGED
|
@@ -6,6 +6,64 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.StreamFormatter = exports.formatMarkdown = exports.showToolProgress = exports.showTodoList = exports.showDiff = exports.banner = exports.log = void 0;
|
|
7
7
|
const chalk_1 = __importDefault(require("chalk"));
|
|
8
8
|
const diff_1 = require("diff");
|
|
9
|
+
// Simple ASCII art letters for custom banners
|
|
10
|
+
const ASCII_LETTERS = {
|
|
11
|
+
A: [" █ ", " █ █ ", "█████", "█ █", "█ █"],
|
|
12
|
+
B: ["████ ", "█ █", "████ ", "█ █", "████ "],
|
|
13
|
+
C: [" ████", "█ ", "█ ", "█ ", " ████"],
|
|
14
|
+
D: ["████ ", "█ █", "█ █", "█ █", "████ "],
|
|
15
|
+
E: ["█████", "█ ", "████ ", "█ ", "█████"],
|
|
16
|
+
F: ["█████", "█ ", "████ ", "█ ", "█ "],
|
|
17
|
+
G: [" ████", "█ ", "█ ██", "█ █", " ████"],
|
|
18
|
+
H: ["█ █", "█ █", "█████", "█ █", "█ █"],
|
|
19
|
+
I: ["█████", " █ ", " █ ", " █ ", "█████"],
|
|
20
|
+
J: ["█████", " █ ", " █ ", "█ █ ", " ██ "],
|
|
21
|
+
K: ["█ █", "█ █ ", "███ ", "█ █ ", "█ █"],
|
|
22
|
+
L: ["█ ", "█ ", "█ ", "█ ", "█████"],
|
|
23
|
+
M: ["█ █", "██ ██", "█ █ █", "█ █", "█ █"],
|
|
24
|
+
N: ["█ █", "██ █", "█ █ █", "█ ██", "█ █"],
|
|
25
|
+
O: [" ███ ", "█ █", "█ █", "█ █", " ███ "],
|
|
26
|
+
P: ["████ ", "█ █", "████ ", "█ ", "█ "],
|
|
27
|
+
Q: [" ███ ", "█ █", "█ █ █", "█ █ ", " ██ █"],
|
|
28
|
+
R: ["████ ", "█ █", "████ ", "█ █ ", "█ █"],
|
|
29
|
+
S: [" ████", "█ ", " ███ ", " █", "████ "],
|
|
30
|
+
T: ["█████", " █ ", " █ ", " █ ", " █ "],
|
|
31
|
+
U: ["█ █", "█ █", "█ █", "█ █", " ███ "],
|
|
32
|
+
V: ["█ █", "█ █", "█ █", " █ █ ", " █ "],
|
|
33
|
+
W: ["█ █", "█ █", "█ █ █", "██ ██", "█ █"],
|
|
34
|
+
X: ["█ █", " █ █ ", " █ ", " █ █ ", "█ █"],
|
|
35
|
+
Y: ["█ █", " █ █ ", " █ ", " █ ", " █ "],
|
|
36
|
+
Z: ["█████", " █ ", " █ ", " █ ", "█████"],
|
|
37
|
+
" ": [" ", " ", " ", " ", " "],
|
|
38
|
+
"-": [" ", " ", "█████", " ", " "],
|
|
39
|
+
_: [" ", " ", " ", " ", "█████"],
|
|
40
|
+
".": [" ", " ", " ", " ", " █ "],
|
|
41
|
+
"!": [" █ ", " █ ", " █ ", " ", " █ "],
|
|
42
|
+
"0": [" ███ ", "█ █", "█ █", "█ █", " ███ "],
|
|
43
|
+
"1": [" █ ", " ██ ", " █ ", " █ ", " ███ "],
|
|
44
|
+
"2": [" ███ ", "█ █", " ██ ", " █ ", "█████"],
|
|
45
|
+
"3": ["████ ", " █", " ███ ", " █", "████ "],
|
|
46
|
+
"4": ["█ █", "█ █", "█████", " █", " █"],
|
|
47
|
+
"5": ["█████", "█ ", "████ ", " █", "████ "],
|
|
48
|
+
"6": [" ███ ", "█ ", "████ ", "█ █", " ███ "],
|
|
49
|
+
"7": ["█████", " █", " █ ", " █ ", " █ "],
|
|
50
|
+
"8": [" ███ ", "█ █", " ███ ", "█ █", " ███ "],
|
|
51
|
+
"9": [" ███ ", "█ █", " ████", " █", " ███ "],
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Generate ASCII art banner from text
|
|
55
|
+
*/
|
|
56
|
+
const generateAsciiBanner = (text) => {
|
|
57
|
+
const upperText = text.toUpperCase();
|
|
58
|
+
const lines = ["", "", "", "", ""];
|
|
59
|
+
for (const char of upperText) {
|
|
60
|
+
const letterArt = ASCII_LETTERS[char] || ASCII_LETTERS[" "];
|
|
61
|
+
for (let i = 0; i < 5; i++) {
|
|
62
|
+
lines[i] += letterArt[i] + " ";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return lines.join("\n");
|
|
66
|
+
};
|
|
9
67
|
// Syntax highlighting color schemes for different languages
|
|
10
68
|
const syntaxColors = {
|
|
11
69
|
keyword: chalk_1.default.magenta,
|
|
@@ -21,33 +79,147 @@ const syntaxColors = {
|
|
|
21
79
|
// Common keywords for different languages
|
|
22
80
|
const keywords = new Set([
|
|
23
81
|
// JavaScript/TypeScript
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
82
|
+
"const",
|
|
83
|
+
"let",
|
|
84
|
+
"var",
|
|
85
|
+
"function",
|
|
86
|
+
"return",
|
|
87
|
+
"if",
|
|
88
|
+
"else",
|
|
89
|
+
"for",
|
|
90
|
+
"while",
|
|
91
|
+
"do",
|
|
92
|
+
"switch",
|
|
93
|
+
"case",
|
|
94
|
+
"break",
|
|
95
|
+
"continue",
|
|
96
|
+
"try",
|
|
97
|
+
"catch",
|
|
98
|
+
"finally",
|
|
99
|
+
"throw",
|
|
100
|
+
"class",
|
|
101
|
+
"extends",
|
|
102
|
+
"new",
|
|
103
|
+
"this",
|
|
104
|
+
"super",
|
|
105
|
+
"import",
|
|
106
|
+
"export",
|
|
107
|
+
"from",
|
|
108
|
+
"as",
|
|
109
|
+
"default",
|
|
110
|
+
"async",
|
|
111
|
+
"await",
|
|
112
|
+
"yield",
|
|
113
|
+
"typeof",
|
|
114
|
+
"instanceof",
|
|
115
|
+
"in",
|
|
116
|
+
"of",
|
|
117
|
+
"true",
|
|
118
|
+
"false",
|
|
119
|
+
"null",
|
|
120
|
+
"undefined",
|
|
121
|
+
"void",
|
|
122
|
+
"delete",
|
|
123
|
+
"static",
|
|
124
|
+
"get",
|
|
125
|
+
"set",
|
|
126
|
+
"interface",
|
|
127
|
+
"type",
|
|
128
|
+
"enum",
|
|
129
|
+
"implements",
|
|
130
|
+
"private",
|
|
131
|
+
"public",
|
|
132
|
+
"protected",
|
|
30
133
|
// Python
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
134
|
+
"def",
|
|
135
|
+
"class",
|
|
136
|
+
"import",
|
|
137
|
+
"from",
|
|
138
|
+
"as",
|
|
139
|
+
"if",
|
|
140
|
+
"elif",
|
|
141
|
+
"else",
|
|
142
|
+
"for",
|
|
143
|
+
"while",
|
|
144
|
+
"try",
|
|
145
|
+
"except",
|
|
146
|
+
"finally",
|
|
147
|
+
"raise",
|
|
148
|
+
"with",
|
|
149
|
+
"lambda",
|
|
150
|
+
"return",
|
|
151
|
+
"yield",
|
|
152
|
+
"True",
|
|
153
|
+
"False",
|
|
154
|
+
"None",
|
|
155
|
+
"and",
|
|
156
|
+
"or",
|
|
157
|
+
"not",
|
|
158
|
+
"is",
|
|
159
|
+
"in",
|
|
160
|
+
"pass",
|
|
161
|
+
"global",
|
|
162
|
+
"nonlocal",
|
|
163
|
+
"assert",
|
|
164
|
+
"break",
|
|
165
|
+
"continue",
|
|
166
|
+
"self",
|
|
167
|
+
"async",
|
|
168
|
+
"await",
|
|
35
169
|
// Go
|
|
36
|
-
|
|
37
|
-
|
|
170
|
+
"func",
|
|
171
|
+
"package",
|
|
172
|
+
"import",
|
|
173
|
+
"type",
|
|
174
|
+
"struct",
|
|
175
|
+
"interface",
|
|
176
|
+
"map",
|
|
177
|
+
"chan",
|
|
178
|
+
"go",
|
|
179
|
+
"defer",
|
|
180
|
+
"select",
|
|
181
|
+
"range",
|
|
182
|
+
"make",
|
|
183
|
+
"append",
|
|
184
|
+
"len",
|
|
185
|
+
"cap",
|
|
186
|
+
"nil",
|
|
38
187
|
// Rust
|
|
39
|
-
|
|
40
|
-
|
|
188
|
+
"fn",
|
|
189
|
+
"let",
|
|
190
|
+
"mut",
|
|
191
|
+
"pub",
|
|
192
|
+
"mod",
|
|
193
|
+
"use",
|
|
194
|
+
"struct",
|
|
195
|
+
"enum",
|
|
196
|
+
"impl",
|
|
197
|
+
"trait",
|
|
198
|
+
"match",
|
|
199
|
+
"loop",
|
|
200
|
+
"move",
|
|
201
|
+
"ref",
|
|
202
|
+
"self",
|
|
203
|
+
"Self",
|
|
204
|
+
"where",
|
|
205
|
+
"unsafe",
|
|
206
|
+
"async",
|
|
41
207
|
// Common
|
|
42
|
-
|
|
208
|
+
"print",
|
|
209
|
+
"println",
|
|
210
|
+
"printf",
|
|
211
|
+
"console",
|
|
212
|
+
"log",
|
|
213
|
+
"error",
|
|
214
|
+
"warn",
|
|
43
215
|
]);
|
|
44
216
|
/**
|
|
45
217
|
* Truncate output for brief display
|
|
46
218
|
*/
|
|
47
219
|
const truncateOutput = (text, maxLen) => {
|
|
48
|
-
const firstLine = text.split(
|
|
220
|
+
const firstLine = text.split("\n")[0];
|
|
49
221
|
if (firstLine.length > maxLen) {
|
|
50
|
-
return firstLine.substring(0, maxLen) +
|
|
222
|
+
return firstLine.substring(0, maxLen) + "...";
|
|
51
223
|
}
|
|
52
224
|
return firstLine;
|
|
53
225
|
};
|
|
@@ -55,97 +227,102 @@ const truncateOutput = (text, maxLen) => {
|
|
|
55
227
|
* Format diff output with colors
|
|
56
228
|
*/
|
|
57
229
|
const formatDiffOutput = (output) => {
|
|
58
|
-
const lines = output.split(
|
|
59
|
-
return lines
|
|
230
|
+
const lines = output.split("\n");
|
|
231
|
+
return lines
|
|
232
|
+
.map((line) => {
|
|
60
233
|
// File headers
|
|
61
|
-
if (line.startsWith(
|
|
234
|
+
if (line.startsWith("diff --git")) {
|
|
62
235
|
return chalk_1.default.bold.white(line);
|
|
63
236
|
}
|
|
64
|
-
if (line.startsWith(
|
|
237
|
+
if (line.startsWith("index ")) {
|
|
65
238
|
return chalk_1.default.gray(line);
|
|
66
239
|
}
|
|
67
|
-
if (line.startsWith(
|
|
240
|
+
if (line.startsWith("---")) {
|
|
68
241
|
return chalk_1.default.red.bold(line);
|
|
69
242
|
}
|
|
70
|
-
if (line.startsWith(
|
|
243
|
+
if (line.startsWith("+++")) {
|
|
71
244
|
return chalk_1.default.green.bold(line);
|
|
72
245
|
}
|
|
73
246
|
// Hunk headers
|
|
74
|
-
if (line.startsWith(
|
|
247
|
+
if (line.startsWith("@@")) {
|
|
75
248
|
return chalk_1.default.cyan(line);
|
|
76
249
|
}
|
|
77
250
|
// Added lines
|
|
78
|
-
if (line.startsWith(
|
|
251
|
+
if (line.startsWith("+")) {
|
|
79
252
|
return chalk_1.default.green(line);
|
|
80
253
|
}
|
|
81
254
|
// Removed lines
|
|
82
|
-
if (line.startsWith(
|
|
255
|
+
if (line.startsWith("-")) {
|
|
83
256
|
return chalk_1.default.red(line);
|
|
84
257
|
}
|
|
85
258
|
// Context lines
|
|
86
259
|
return chalk_1.default.gray(line);
|
|
87
|
-
})
|
|
260
|
+
})
|
|
261
|
+
.join("\n");
|
|
88
262
|
};
|
|
89
263
|
/**
|
|
90
264
|
* Format git log output with colors
|
|
91
265
|
*/
|
|
92
266
|
const formatGitLogOutput = (output) => {
|
|
93
|
-
const lines = output.split(
|
|
94
|
-
return lines
|
|
267
|
+
const lines = output.split("\n");
|
|
268
|
+
return lines
|
|
269
|
+
.map((line) => {
|
|
95
270
|
// Commit hash
|
|
96
271
|
if (line.match(/^[a-f0-9]{7,40}\s/)) {
|
|
97
|
-
const parts = line.split(
|
|
272
|
+
const parts = line.split(" ");
|
|
98
273
|
const hash = parts[0];
|
|
99
|
-
const rest = parts.slice(1).join(
|
|
100
|
-
return chalk_1.default.yellow(hash) +
|
|
274
|
+
const rest = parts.slice(1).join(" ");
|
|
275
|
+
return chalk_1.default.yellow(hash) + " " + rest;
|
|
101
276
|
}
|
|
102
277
|
// Date lines
|
|
103
278
|
if (line.match(/^\d{4}-\d{2}-\d{2}/)) {
|
|
104
279
|
return chalk_1.default.blue(line);
|
|
105
280
|
}
|
|
106
281
|
// Author
|
|
107
|
-
if (line.toLowerCase().includes(
|
|
282
|
+
if (line.toLowerCase().includes("author:")) {
|
|
108
283
|
return chalk_1.default.cyan(line);
|
|
109
284
|
}
|
|
110
285
|
// Commit message (indented)
|
|
111
|
-
if (line.startsWith(
|
|
286
|
+
if (line.startsWith(" ")) {
|
|
112
287
|
return chalk_1.default.white(line);
|
|
113
288
|
}
|
|
114
289
|
return line;
|
|
115
|
-
})
|
|
290
|
+
})
|
|
291
|
+
.join("\n");
|
|
116
292
|
};
|
|
117
293
|
/**
|
|
118
294
|
* Format git status output with colors
|
|
119
295
|
*/
|
|
120
296
|
const formatGitStatusOutput = (output) => {
|
|
121
|
-
const lines = output.split(
|
|
122
|
-
return lines
|
|
297
|
+
const lines = output.split("\n");
|
|
298
|
+
return lines
|
|
299
|
+
.map((line) => {
|
|
123
300
|
// Branch info
|
|
124
|
-
if (line.startsWith(
|
|
301
|
+
if (line.startsWith("On branch") || line.startsWith("HEAD detached")) {
|
|
125
302
|
return chalk_1.default.cyan.bold(line);
|
|
126
303
|
}
|
|
127
304
|
// Modified files
|
|
128
|
-
if (line.includes(
|
|
305
|
+
if (line.includes("modified:")) {
|
|
129
306
|
return chalk_1.default.yellow(line);
|
|
130
307
|
}
|
|
131
308
|
// New files
|
|
132
|
-
if (line.includes(
|
|
309
|
+
if (line.includes("new file:")) {
|
|
133
310
|
return chalk_1.default.green(line);
|
|
134
311
|
}
|
|
135
312
|
// Deleted files
|
|
136
|
-
if (line.includes(
|
|
313
|
+
if (line.includes("deleted:")) {
|
|
137
314
|
return chalk_1.default.red(line);
|
|
138
315
|
}
|
|
139
316
|
// Untracked files header
|
|
140
|
-
if (line.includes(
|
|
317
|
+
if (line.includes("Untracked files:")) {
|
|
141
318
|
return chalk_1.default.magenta.bold(line);
|
|
142
319
|
}
|
|
143
320
|
// Staged changes header
|
|
144
|
-
if (line.includes(
|
|
321
|
+
if (line.includes("Changes to be committed:")) {
|
|
145
322
|
return chalk_1.default.green.bold(line);
|
|
146
323
|
}
|
|
147
324
|
// Unstaged changes header
|
|
148
|
-
if (line.includes(
|
|
325
|
+
if (line.includes("Changes not staged")) {
|
|
149
326
|
return chalk_1.default.yellow.bold(line);
|
|
150
327
|
}
|
|
151
328
|
// File status indicators (M, A, D, ??)
|
|
@@ -155,19 +332,20 @@ const formatGitStatusOutput = (output) => {
|
|
|
155
332
|
const indicator = status[1];
|
|
156
333
|
const filename = status[2];
|
|
157
334
|
let color = chalk_1.default.white;
|
|
158
|
-
if (indicator.includes(
|
|
335
|
+
if (indicator.includes("M"))
|
|
159
336
|
color = chalk_1.default.yellow;
|
|
160
|
-
if (indicator.includes(
|
|
337
|
+
if (indicator.includes("A"))
|
|
161
338
|
color = chalk_1.default.green;
|
|
162
|
-
if (indicator.includes(
|
|
339
|
+
if (indicator.includes("D"))
|
|
163
340
|
color = chalk_1.default.red;
|
|
164
|
-
if (indicator.includes(
|
|
341
|
+
if (indicator.includes("?"))
|
|
165
342
|
color = chalk_1.default.gray;
|
|
166
343
|
return color(` ${indicator} ${filename}`);
|
|
167
344
|
}
|
|
168
345
|
}
|
|
169
346
|
return chalk_1.default.gray(line);
|
|
170
|
-
})
|
|
347
|
+
})
|
|
348
|
+
.join("\n");
|
|
171
349
|
};
|
|
172
350
|
/**
|
|
173
351
|
* Apply syntax highlighting to a line of code
|
|
@@ -200,21 +378,24 @@ const highlightCodeLine = (line) => {
|
|
|
200
378
|
/**
|
|
201
379
|
* Format file content with line numbers and syntax highlighting
|
|
202
380
|
*/
|
|
203
|
-
const formatFileContent = (content,
|
|
204
|
-
const lines = content.split(
|
|
381
|
+
const formatFileContent = (content, _filename) => {
|
|
382
|
+
const lines = content.split("\n");
|
|
205
383
|
const lineNumWidth = String(lines.length).length;
|
|
206
|
-
return lines
|
|
207
|
-
|
|
384
|
+
return lines
|
|
385
|
+
.map((line, idx) => {
|
|
386
|
+
const lineNum = String(idx + 1).padStart(lineNumWidth, " ");
|
|
208
387
|
const highlighted = highlightCodeLine(line);
|
|
209
388
|
return chalk_1.default.gray(`${lineNum} │ `) + highlighted;
|
|
210
|
-
})
|
|
389
|
+
})
|
|
390
|
+
.join("\n");
|
|
211
391
|
};
|
|
212
392
|
/**
|
|
213
393
|
* Format bash command output
|
|
214
394
|
*/
|
|
215
395
|
const formatBashOutput = (output) => {
|
|
216
396
|
// Check if it looks like a diff
|
|
217
|
-
if (output.includes(
|
|
397
|
+
if (output.includes("diff --git") ||
|
|
398
|
+
(output.includes("@@") && (output.includes("+") || output.includes("-")))) {
|
|
218
399
|
return formatDiffOutput(output);
|
|
219
400
|
}
|
|
220
401
|
// Check if it looks like git log
|
|
@@ -222,18 +403,21 @@ const formatBashOutput = (output) => {
|
|
|
222
403
|
return formatGitLogOutput(output);
|
|
223
404
|
}
|
|
224
405
|
// Generic output with some highlighting
|
|
225
|
-
const lines = output.split(
|
|
226
|
-
return lines
|
|
406
|
+
const lines = output.split("\n");
|
|
407
|
+
return lines
|
|
408
|
+
.map((line) => {
|
|
227
409
|
// Error messages
|
|
228
|
-
if (line.toLowerCase().includes(
|
|
410
|
+
if (line.toLowerCase().includes("error") || line.toLowerCase().includes("failed")) {
|
|
229
411
|
return chalk_1.default.red(line);
|
|
230
412
|
}
|
|
231
413
|
// Warning messages
|
|
232
|
-
if (line.toLowerCase().includes(
|
|
414
|
+
if (line.toLowerCase().includes("warning") || line.toLowerCase().includes("warn")) {
|
|
233
415
|
return chalk_1.default.yellow(line);
|
|
234
416
|
}
|
|
235
417
|
// Success messages
|
|
236
|
-
if (line.toLowerCase().includes(
|
|
418
|
+
if (line.toLowerCase().includes("success") ||
|
|
419
|
+
line.toLowerCase().includes("done") ||
|
|
420
|
+
line.toLowerCase().includes("passed")) {
|
|
237
421
|
return chalk_1.default.green(line);
|
|
238
422
|
}
|
|
239
423
|
// Paths
|
|
@@ -241,53 +425,56 @@ const formatBashOutput = (output) => {
|
|
|
241
425
|
return chalk_1.default.cyan(line);
|
|
242
426
|
}
|
|
243
427
|
return line;
|
|
244
|
-
})
|
|
428
|
+
})
|
|
429
|
+
.join("\n");
|
|
245
430
|
};
|
|
246
431
|
/**
|
|
247
432
|
* Format tool output based on tool type
|
|
248
433
|
*/
|
|
249
434
|
const formatToolOutput = (toolName, output) => {
|
|
250
|
-
if (!output || output.trim() ===
|
|
251
|
-
return chalk_1.default.gray(
|
|
435
|
+
if (!output || output.trim() === "") {
|
|
436
|
+
return chalk_1.default.gray(" (no output)");
|
|
252
437
|
}
|
|
253
|
-
const separator = chalk_1.default.gray('─'.repeat(60));
|
|
254
438
|
let formatted;
|
|
255
439
|
switch (toolName.toLowerCase()) {
|
|
256
|
-
case
|
|
257
|
-
case
|
|
440
|
+
case "git_diff":
|
|
441
|
+
case "gitdiff":
|
|
258
442
|
formatted = formatDiffOutput(output);
|
|
259
443
|
break;
|
|
260
|
-
case
|
|
261
|
-
case
|
|
444
|
+
case "git_log":
|
|
445
|
+
case "gitlog":
|
|
262
446
|
formatted = formatGitLogOutput(output);
|
|
263
447
|
break;
|
|
264
|
-
case
|
|
265
|
-
case
|
|
448
|
+
case "git_status":
|
|
449
|
+
case "gitstatus":
|
|
266
450
|
formatted = formatGitStatusOutput(output);
|
|
267
451
|
break;
|
|
268
|
-
case
|
|
269
|
-
case
|
|
452
|
+
case "read_file":
|
|
453
|
+
case "readfile":
|
|
270
454
|
formatted = formatFileContent(output);
|
|
271
455
|
break;
|
|
272
|
-
case
|
|
273
|
-
case
|
|
456
|
+
case "bash":
|
|
457
|
+
case "shell":
|
|
274
458
|
formatted = formatBashOutput(output);
|
|
275
459
|
break;
|
|
276
|
-
case
|
|
277
|
-
case
|
|
460
|
+
case "glob":
|
|
461
|
+
case "grep":
|
|
278
462
|
// File lists - highlight paths
|
|
279
|
-
formatted = output
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
463
|
+
formatted = output
|
|
464
|
+
.split("\n")
|
|
465
|
+
.map((line) => {
|
|
466
|
+
if (line.includes(":")) {
|
|
467
|
+
const [path, ...rest] = line.split(":");
|
|
468
|
+
return chalk_1.default.cyan(path) + ":" + chalk_1.default.white(rest.join(":"));
|
|
283
469
|
}
|
|
284
470
|
return chalk_1.default.cyan(line);
|
|
285
|
-
})
|
|
471
|
+
})
|
|
472
|
+
.join("\n");
|
|
286
473
|
break;
|
|
287
474
|
default:
|
|
288
475
|
formatted = output;
|
|
289
476
|
}
|
|
290
|
-
return `\n${chalk_1.default.gray(
|
|
477
|
+
return `\n${chalk_1.default.gray("Output:")}\n${formatted}`;
|
|
291
478
|
};
|
|
292
479
|
exports.log = {
|
|
293
480
|
info: (msg) => console.log(chalk_1.default.blue("ℹ"), msg),
|
|
@@ -313,14 +500,18 @@ exports.log = {
|
|
|
313
500
|
console.log(formatted);
|
|
314
501
|
},
|
|
315
502
|
};
|
|
316
|
-
const banner = (modelName, toolCount) => {
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
503
|
+
const banner = (modelName, toolCount, customization) => {
|
|
504
|
+
const cliName = customization?.cliName || "Prab CLI";
|
|
505
|
+
const userName = customization?.userName;
|
|
506
|
+
const theme = customization?.theme || "default";
|
|
507
|
+
// Choose color based on theme
|
|
508
|
+
const titleColor = theme === "colorful" ? chalk_1.default.bold.magenta : theme === "minimal" ? chalk_1.default.white : chalk_1.default.bold.cyan;
|
|
509
|
+
// Generate ASCII art for the CLI name
|
|
510
|
+
const asciiBanner = generateAsciiBanner(cliName);
|
|
511
|
+
console.log(titleColor("\n" + asciiBanner));
|
|
512
|
+
if (userName) {
|
|
513
|
+
console.log(chalk_1.default.gray(` Welcome, ${chalk_1.default.cyan(userName)}!`));
|
|
514
|
+
}
|
|
324
515
|
if (modelName) {
|
|
325
516
|
console.log(chalk_1.default.gray(` Active Model: ${chalk_1.default.cyan(modelName)}`));
|
|
326
517
|
}
|
|
@@ -339,11 +530,7 @@ const showDiff = (before, after, filename) => {
|
|
|
339
530
|
}
|
|
340
531
|
const diff = (0, diff_1.diffLines)(before, after);
|
|
341
532
|
diff.forEach((part) => {
|
|
342
|
-
const color = part.added
|
|
343
|
-
? chalk_1.default.green
|
|
344
|
-
: part.removed
|
|
345
|
-
? chalk_1.default.red
|
|
346
|
-
: chalk_1.default.gray;
|
|
533
|
+
const color = part.added ? chalk_1.default.green : part.removed ? chalk_1.default.red : chalk_1.default.gray;
|
|
347
534
|
const prefix = part.added ? "+ " : part.removed ? "- " : " ";
|
|
348
535
|
const lines = part.value.split("\n");
|
|
349
536
|
lines.forEach((line) => {
|
|
@@ -364,7 +551,7 @@ const showTodoList = (todos) => {
|
|
|
364
551
|
return;
|
|
365
552
|
}
|
|
366
553
|
console.log(chalk_1.default.bold("\n📋 Todo List:"));
|
|
367
|
-
todos.forEach((todo,
|
|
554
|
+
todos.forEach((todo, _index) => {
|
|
368
555
|
const status = todo.status === "completed"
|
|
369
556
|
? chalk_1.default.green("✓")
|
|
370
557
|
: todo.status === "in_progress"
|
|
@@ -386,11 +573,7 @@ exports.showTodoList = showTodoList;
|
|
|
386
573
|
*/
|
|
387
574
|
const showToolProgress = (toolName, status) => {
|
|
388
575
|
const icon = status === "started" ? "⏳" : status === "completed" ? "✓" : "✗";
|
|
389
|
-
const color = status === "started"
|
|
390
|
-
? chalk_1.default.yellow
|
|
391
|
-
: status === "completed"
|
|
392
|
-
? chalk_1.default.green
|
|
393
|
-
: chalk_1.default.red;
|
|
576
|
+
const color = status === "started" ? chalk_1.default.yellow : status === "completed" ? chalk_1.default.green : chalk_1.default.red;
|
|
394
577
|
console.log(color(`${icon} ${toolName} ${status}`));
|
|
395
578
|
};
|
|
396
579
|
exports.showToolProgress = showToolProgress;
|
|
@@ -402,19 +585,16 @@ const formatCodeBlock = (code, language) => {
|
|
|
402
585
|
const maxLineLen = Math.max(...lines.map((l) => l.length), 40);
|
|
403
586
|
const boxWidth = Math.min(maxLineLen + 4, 80);
|
|
404
587
|
const langLabel = language ? chalk_1.default.cyan.bold(` ${language} `) : "";
|
|
405
|
-
const topBorder = chalk_1.default.gray("╭") +
|
|
588
|
+
const topBorder = chalk_1.default.gray("╭") +
|
|
589
|
+
langLabel +
|
|
590
|
+
chalk_1.default.gray("─".repeat(Math.max(0, boxWidth - language.length - 3))) +
|
|
591
|
+
chalk_1.default.gray("╮");
|
|
406
592
|
const bottomBorder = chalk_1.default.gray("╰" + "─".repeat(boxWidth - 1) + "╯");
|
|
407
593
|
const formattedLines = lines.map((line) => {
|
|
408
594
|
const highlighted = highlightCodeLine(line);
|
|
409
595
|
return chalk_1.default.gray("│ ") + highlighted;
|
|
410
596
|
});
|
|
411
|
-
return [
|
|
412
|
-
"",
|
|
413
|
-
topBorder,
|
|
414
|
-
...formattedLines,
|
|
415
|
-
bottomBorder,
|
|
416
|
-
"",
|
|
417
|
-
].join("\n");
|
|
597
|
+
return ["", topBorder, ...formattedLines, bottomBorder, ""].join("\n");
|
|
418
598
|
};
|
|
419
599
|
/**
|
|
420
600
|
* Format markdown text with colors for terminal display
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prab-cli",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "AI-powered coding assistant for your terminal. Built with Groq's lightning-fast LLMs, featuring autonomous tool execution, syntax-highlighted output, and git integration.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -15,8 +15,21 @@
|
|
|
15
15
|
"log": "ts-node src/log-viewer.ts",
|
|
16
16
|
"log:list": "ts-node src/log-viewer.ts list",
|
|
17
17
|
"log:help": "ts-node src/log-viewer.ts help",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
18
|
+
"lint": "eslint src/**/*.ts",
|
|
19
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
20
|
+
"format": "prettier --write src/**/*.ts",
|
|
21
|
+
"format:check": "prettier --check src/**/*.ts",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"validate": "npm run lint && npm run typecheck && npm run build",
|
|
24
|
+
"prepublishOnly": "npm run validate",
|
|
25
|
+
"test": "npm run validate",
|
|
26
|
+
"prepare": "husky"
|
|
27
|
+
},
|
|
28
|
+
"lint-staged": {
|
|
29
|
+
"src/**/*.ts": [
|
|
30
|
+
"eslint --fix",
|
|
31
|
+
"prettier --write"
|
|
32
|
+
]
|
|
20
33
|
},
|
|
21
34
|
"keywords": [
|
|
22
35
|
"cli",
|
|
@@ -66,11 +79,20 @@
|
|
|
66
79
|
"zod": "^4.3.5"
|
|
67
80
|
},
|
|
68
81
|
"devDependencies": {
|
|
82
|
+
"@eslint/js": "^9.39.2",
|
|
69
83
|
"@types/diff": "^7.0.2",
|
|
70
84
|
"@types/glob": "^8.1.0",
|
|
71
85
|
"@types/inquirer": "^9.0.9",
|
|
72
86
|
"@types/node": "^25.0.3",
|
|
87
|
+
"@typescript-eslint/eslint-plugin": "^8.53.1",
|
|
88
|
+
"@typescript-eslint/parser": "^8.53.1",
|
|
89
|
+
"eslint": "^9.39.2",
|
|
90
|
+
"eslint-config-prettier": "^10.1.8",
|
|
91
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
92
|
+
"husky": "^9.1.7",
|
|
93
|
+
"lint-staged": "^16.2.7",
|
|
73
94
|
"nodemon": "^3.1.11",
|
|
95
|
+
"prettier": "^3.8.0",
|
|
74
96
|
"ts-node": "^10.9.2",
|
|
75
97
|
"typescript": "^5.9.3"
|
|
76
98
|
}
|