prab-cli 1.0.0 → 1.1.0
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 +168 -166
- package/dist/lib/chat-handler.js +20 -0
- package/dist/lib/slash-commands.js +94 -0
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
3
36
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
37
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
38
|
};
|
|
@@ -10,6 +43,8 @@ const config_1 = require("./lib/config");
|
|
|
10
43
|
const context_1 = require("./lib/context");
|
|
11
44
|
const ui_1 = require("./lib/ui");
|
|
12
45
|
const config_2 = require("./lib/config");
|
|
46
|
+
const slash_commands_1 = require("./lib/slash-commands");
|
|
47
|
+
const select_1 = __importStar(require("@inquirer/select"));
|
|
13
48
|
const ora_1 = __importDefault(require("ora"));
|
|
14
49
|
// Import tool system
|
|
15
50
|
const base_1 = require("./lib/tools/base");
|
|
@@ -176,7 +211,7 @@ program.action(async () => {
|
|
|
176
211
|
}
|
|
177
212
|
// Initialize chat handler
|
|
178
213
|
const chatHandler = new chat_handler_1.ChatHandler(toolRegistry, toolExecutor, modelProvider, contextMessage);
|
|
179
|
-
ui_1.log.info('Type "/" for commands
|
|
214
|
+
ui_1.log.info('Type "/" for commands (searchable), or start chatting!');
|
|
180
215
|
// Display any existing todos
|
|
181
216
|
const session = (0, config_2.getSessionData)();
|
|
182
217
|
if (session.todos && session.todos.length > 0) {
|
|
@@ -191,180 +226,147 @@ program.action(async () => {
|
|
|
191
226
|
message: ">",
|
|
192
227
|
},
|
|
193
228
|
]);
|
|
194
|
-
// Handle Slash Commands
|
|
195
|
-
if (userInput.trim() === "/") {
|
|
229
|
+
// Handle Slash Commands
|
|
230
|
+
if (userInput.trim() === "/" || userInput.trim().startsWith("/")) {
|
|
196
231
|
const currentModel = modelProvider.modelId;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
"
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
const isCurrent = model.id === currentModel;
|
|
234
|
-
const ctx = (0, groq_models_1.formatContextWindow)(model.context_window);
|
|
235
|
-
modelChoices.push({
|
|
236
|
-
name: `${isCurrent ? "✓ " : " "}${model.id} (${ctx} ctx)`,
|
|
237
|
-
value: model.id,
|
|
238
|
-
short: model.id,
|
|
232
|
+
// Show the searchable slash command menu
|
|
233
|
+
const action = await (0, slash_commands_1.showSlashCommandMenu)();
|
|
234
|
+
if (!action) {
|
|
235
|
+
// User cancelled
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
// Execute the selected command
|
|
239
|
+
switch (action) {
|
|
240
|
+
case "model": {
|
|
241
|
+
// Fetch models from Groq API if not cached
|
|
242
|
+
if (cachedModels.length === 0) {
|
|
243
|
+
const spinner = (0, ora_1.default)("Fetching available models from Groq...").start();
|
|
244
|
+
cachedModels = await (0, groq_models_1.fetchGroqModels)(apiKey);
|
|
245
|
+
spinner.succeed(`Found ${cachedModels.length} models`);
|
|
246
|
+
}
|
|
247
|
+
// Group models by owner
|
|
248
|
+
const grouped = (0, groq_models_1.groupModelsByOwner)(cachedModels);
|
|
249
|
+
const modelChoices = [];
|
|
250
|
+
// Build choices grouped by owner
|
|
251
|
+
for (const [owner, models] of grouped) {
|
|
252
|
+
modelChoices.push(new select_1.Separator(`─── ${owner} ───`));
|
|
253
|
+
for (const model of models) {
|
|
254
|
+
const isCurrent = model.id === currentModel;
|
|
255
|
+
const ctx = (0, groq_models_1.formatContextWindow)(model.context_window);
|
|
256
|
+
modelChoices.push({
|
|
257
|
+
name: `${isCurrent ? "✓ " : " "}${model.id} (${ctx} ctx)`,
|
|
258
|
+
value: model.id,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
try {
|
|
263
|
+
const selectedModel = await (0, select_1.default)({
|
|
264
|
+
message: `Select a model (current: ${currentModel}):`,
|
|
265
|
+
choices: modelChoices,
|
|
266
|
+
pageSize: 15,
|
|
267
|
+
loop: false,
|
|
239
268
|
});
|
|
269
|
+
if (selectedModel && selectedModel !== currentModel) {
|
|
270
|
+
const oldModel = currentModel;
|
|
271
|
+
(0, config_1.setActiveModel)(selectedModel);
|
|
272
|
+
modelProvider.setModel(selectedModel);
|
|
273
|
+
ui_1.log.success(`Switched to model: ${selectedModel}`);
|
|
274
|
+
tracker_1.tracker.modelSwitch(oldModel, selectedModel, true);
|
|
275
|
+
}
|
|
276
|
+
else if (selectedModel === currentModel) {
|
|
277
|
+
ui_1.log.info(`Already using ${selectedModel}`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
// User cancelled with Ctrl+C
|
|
240
282
|
}
|
|
283
|
+
break;
|
|
241
284
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
285
|
+
case "usage": {
|
|
286
|
+
console.log("\n┌─────────────────────────────────────┐");
|
|
287
|
+
console.log("│ MODEL INFO │");
|
|
288
|
+
console.log("└─────────────────────────────────────┘\n");
|
|
289
|
+
console.log(` Current Model: ${currentModel}`);
|
|
290
|
+
// Find model in cache and show details
|
|
291
|
+
if (cachedModels.length === 0) {
|
|
292
|
+
const spinner = (0, ora_1.default)("Fetching model info...").start();
|
|
293
|
+
cachedModels = await (0, groq_models_1.fetchGroqModels)(apiKey);
|
|
294
|
+
spinner.stop();
|
|
295
|
+
}
|
|
296
|
+
const modelInfo = cachedModels.find((m) => m.id === currentModel);
|
|
297
|
+
if (modelInfo) {
|
|
298
|
+
console.log(` Provider: ${modelInfo.owned_by}`);
|
|
299
|
+
console.log(` Context: ${(0, groq_models_1.formatContextWindow)(modelInfo.context_window)} tokens`);
|
|
300
|
+
console.log(` Status: ${modelInfo.active ? "Active" : "Inactive"}`);
|
|
301
|
+
}
|
|
302
|
+
console.log("\n┌─────────────────────────────────────┐");
|
|
303
|
+
console.log("│ TOKEN CONSUMPTION │");
|
|
304
|
+
console.log("└─────────────────────────────────────┘\n");
|
|
305
|
+
const usageStats = chatHandler.getUsageStats();
|
|
306
|
+
console.log(` Prompt Tokens: ${usageStats.promptTokens.toLocaleString()}`);
|
|
307
|
+
console.log(` Completion Tokens: ${usageStats.completionTokens.toLocaleString()}`);
|
|
308
|
+
console.log(` Total Tokens: ${usageStats.totalTokens.toLocaleString()}`);
|
|
309
|
+
console.log(` API Requests: ${usageStats.requestCount}`);
|
|
310
|
+
console.log("\n┌─────────────────────────────────────┐");
|
|
311
|
+
console.log("│ SESSION STATS │");
|
|
312
|
+
console.log("└─────────────────────────────────────┘\n");
|
|
313
|
+
console.log(` Messages: ${chatHandler.getMessageCount()}`);
|
|
314
|
+
console.log(` Tools: ${toolRegistry.count()} available`);
|
|
315
|
+
console.log(` Session ID: ${tracker_1.tracker.getSessionId()}`);
|
|
316
|
+
console.log("");
|
|
317
|
+
break;
|
|
258
318
|
}
|
|
259
|
-
|
|
260
|
-
|
|
319
|
+
case "tools": {
|
|
320
|
+
console.log("\n┌─────────────────────────────────────┐");
|
|
321
|
+
console.log("│ AVAILABLE TOOLS │");
|
|
322
|
+
console.log("└─────────────────────────────────────┘\n");
|
|
323
|
+
console.log(toolRegistry.getToolDescriptions());
|
|
324
|
+
console.log("");
|
|
325
|
+
break;
|
|
261
326
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
console.log("\n┌─────────────────────────────────────┐");
|
|
267
|
-
console.log("│ MODEL USAGE │");
|
|
268
|
-
console.log("└─────────────────────────────────────┘\n");
|
|
269
|
-
console.log(` Current Model: ${currentModel}`);
|
|
270
|
-
// Find model in cache and show details
|
|
271
|
-
if (cachedModels.length === 0) {
|
|
272
|
-
const spinner = (0, ora_1.default)("Fetching model info...").start();
|
|
273
|
-
cachedModels = await (0, groq_models_1.fetchGroqModels)(apiKey);
|
|
274
|
-
spinner.stop();
|
|
327
|
+
case "todos": {
|
|
328
|
+
const session = (0, config_2.getSessionData)();
|
|
329
|
+
(0, ui_1.showTodoList)(session.todos);
|
|
330
|
+
break;
|
|
275
331
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
332
|
+
case "clear-todos": {
|
|
333
|
+
(0, config_1.clearSessionData)();
|
|
334
|
+
ui_1.log.success("Todos cleared.");
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
case "context": {
|
|
338
|
+
console.log("\n┌─────────────────────────────────────┐");
|
|
339
|
+
console.log("│ FILE CONTEXT │");
|
|
340
|
+
console.log("└─────────────────────────────────────┘\n");
|
|
341
|
+
console.log(contextMessage || " No context loaded.");
|
|
342
|
+
console.log("");
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
case "clear": {
|
|
346
|
+
chatHandler.clearHistory();
|
|
347
|
+
ui_1.log.success("Chat history cleared.");
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
case "api-key": {
|
|
351
|
+
const { key } = await inquirer_1.default.prompt([
|
|
352
|
+
{
|
|
353
|
+
type: "password",
|
|
354
|
+
name: "key",
|
|
355
|
+
message: "Enter new API Key:",
|
|
356
|
+
mask: "*",
|
|
357
|
+
},
|
|
358
|
+
]);
|
|
359
|
+
(0, config_1.setApiKey)(key.trim());
|
|
360
|
+
apiKey = key.trim();
|
|
361
|
+
modelProvider.initialize(key.trim(), modelConfig.modelId);
|
|
362
|
+
cachedModels = []; // Clear model cache
|
|
363
|
+
ui_1.log.success("API Key updated.");
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
case "exit": {
|
|
367
|
+
process.exit(0);
|
|
281
368
|
}
|
|
282
|
-
console.log("\n┌─────────────────────────────────────┐");
|
|
283
|
-
console.log("│ SESSION STATS │");
|
|
284
|
-
console.log("└─────────────────────────────────────┘\n");
|
|
285
|
-
console.log(` Messages: ${chatHandler.getMessageCount()}`);
|
|
286
|
-
console.log(` Tools: ${toolRegistry.count()} available`);
|
|
287
|
-
console.log(` Session ID: ${tracker_1.tracker.getSessionId()}`);
|
|
288
|
-
console.log("");
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
if (action === "3. Tools") {
|
|
292
|
-
console.log("\n┌─────────────────────────────────────┐");
|
|
293
|
-
console.log("│ AVAILABLE TOOLS │");
|
|
294
|
-
console.log("└─────────────────────────────────────┘\n");
|
|
295
|
-
console.log(toolRegistry.getToolDescriptions());
|
|
296
|
-
console.log("");
|
|
297
|
-
continue;
|
|
298
|
-
}
|
|
299
|
-
if (action === "4. Todos") {
|
|
300
|
-
const session = (0, config_2.getSessionData)();
|
|
301
|
-
(0, ui_1.showTodoList)(session.todos);
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
if (action === "5. Clear Todos") {
|
|
305
|
-
(0, config_1.clearSessionData)();
|
|
306
|
-
ui_1.log.success("Todos cleared.");
|
|
307
|
-
continue;
|
|
308
|
-
}
|
|
309
|
-
if (action === "6. Context") {
|
|
310
|
-
console.log("\n┌─────────────────────────────────────┐");
|
|
311
|
-
console.log("│ FILE CONTEXT │");
|
|
312
|
-
console.log("└─────────────────────────────────────┘\n");
|
|
313
|
-
console.log(contextMessage || " No context loaded.");
|
|
314
|
-
console.log("");
|
|
315
|
-
continue;
|
|
316
|
-
}
|
|
317
|
-
if (action === "7. Clear History") {
|
|
318
|
-
chatHandler.clearHistory();
|
|
319
|
-
ui_1.log.success("Chat history cleared.");
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
if (action === "8. API Key") {
|
|
323
|
-
const { key } = await inquirer_1.default.prompt([
|
|
324
|
-
{
|
|
325
|
-
type: "password",
|
|
326
|
-
name: "key",
|
|
327
|
-
message: "Enter new API Key:",
|
|
328
|
-
mask: "*",
|
|
329
|
-
},
|
|
330
|
-
]);
|
|
331
|
-
(0, config_1.setApiKey)(key.trim());
|
|
332
|
-
apiKey = key.trim();
|
|
333
|
-
modelProvider.initialize(key.trim(), modelConfig.modelId);
|
|
334
|
-
cachedModels = []; // Clear model cache
|
|
335
|
-
ui_1.log.success("API Key updated.");
|
|
336
|
-
continue;
|
|
337
|
-
}
|
|
338
|
-
if (action === "9. Exit")
|
|
339
|
-
process.exit(0);
|
|
340
|
-
continue;
|
|
341
|
-
}
|
|
342
|
-
// Handle direct slash commands
|
|
343
|
-
if (userInput.startsWith("/")) {
|
|
344
|
-
const cmd = userInput.trim().toLowerCase();
|
|
345
|
-
if (cmd === "/exit" || cmd === "/quit")
|
|
346
|
-
process.exit(0);
|
|
347
|
-
if (cmd === "/clear") {
|
|
348
|
-
chatHandler.clearHistory();
|
|
349
|
-
ui_1.log.success("History cleared.");
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
if (cmd === "/context") {
|
|
353
|
-
ui_1.log.info(contextMessage || "No context.");
|
|
354
|
-
continue;
|
|
355
|
-
}
|
|
356
|
-
if (cmd === "/tools") {
|
|
357
|
-
console.log("\n📦 Available Tools:\n");
|
|
358
|
-
console.log(toolRegistry.getToolDescriptions());
|
|
359
|
-
console.log("");
|
|
360
|
-
continue;
|
|
361
|
-
}
|
|
362
|
-
if (cmd === "/todos") {
|
|
363
|
-
const session = (0, config_2.getSessionData)();
|
|
364
|
-
(0, ui_1.showTodoList)(session.todos);
|
|
365
|
-
continue;
|
|
366
369
|
}
|
|
367
|
-
ui_1.log.warning(`Unknown command: ${cmd}. Type "/" for menu.`);
|
|
368
370
|
continue;
|
|
369
371
|
}
|
|
370
372
|
// Process user input with chat handler
|
package/dist/lib/chat-handler.js
CHANGED
|
@@ -12,6 +12,12 @@ class ChatHandler {
|
|
|
12
12
|
constructor(toolRegistry, toolExecutor, modelProvider, initialContext) {
|
|
13
13
|
this.messages = [];
|
|
14
14
|
this.contextMessage = '';
|
|
15
|
+
this.usage = {
|
|
16
|
+
promptTokens: 0,
|
|
17
|
+
completionTokens: 0,
|
|
18
|
+
totalTokens: 0,
|
|
19
|
+
requestCount: 0,
|
|
20
|
+
};
|
|
15
21
|
this.toolRegistry = toolRegistry;
|
|
16
22
|
this.toolExecutor = toolExecutor;
|
|
17
23
|
this.modelProvider = modelProvider;
|
|
@@ -92,7 +98,15 @@ When you need to perform file operations, use the appropriate tools rather than
|
|
|
92
98
|
if (chunk.tool_calls && chunk.tool_calls.length > 0) {
|
|
93
99
|
toolCalls = chunk.tool_calls;
|
|
94
100
|
}
|
|
101
|
+
// Capture usage metadata from the chunk
|
|
102
|
+
if (chunk.usage_metadata) {
|
|
103
|
+
this.usage.promptTokens += chunk.usage_metadata.input_tokens || 0;
|
|
104
|
+
this.usage.completionTokens += chunk.usage_metadata.output_tokens || 0;
|
|
105
|
+
this.usage.totalTokens += chunk.usage_metadata.total_tokens || 0;
|
|
106
|
+
}
|
|
95
107
|
}
|
|
108
|
+
// Increment request count
|
|
109
|
+
this.usage.requestCount++;
|
|
96
110
|
// Flush any remaining content in the formatter
|
|
97
111
|
const remaining = formatter.flush();
|
|
98
112
|
if (remaining) {
|
|
@@ -205,6 +219,12 @@ When you need to perform file operations, use the appropriate tools rather than
|
|
|
205
219
|
getMessageCount() {
|
|
206
220
|
return this.messages.length;
|
|
207
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Get usage statistics
|
|
224
|
+
*/
|
|
225
|
+
getUsageStats() {
|
|
226
|
+
return { ...this.usage };
|
|
227
|
+
}
|
|
208
228
|
/**
|
|
209
229
|
* Update context (e.g., if file tree changes)
|
|
210
230
|
*/
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SLASH_COMMANDS = void 0;
|
|
7
|
+
exports.showSlashCommandMenu = showSlashCommandMenu;
|
|
8
|
+
const search_1 = __importDefault(require("@inquirer/search"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
exports.SLASH_COMMANDS = [
|
|
11
|
+
{
|
|
12
|
+
name: "/model",
|
|
13
|
+
description: "Switch between available AI models",
|
|
14
|
+
shortcut: "m",
|
|
15
|
+
action: "model",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "/usage",
|
|
19
|
+
description: "Show model info and session statistics",
|
|
20
|
+
shortcut: "u",
|
|
21
|
+
action: "usage",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "/tools",
|
|
25
|
+
description: "List all available tools",
|
|
26
|
+
shortcut: "t",
|
|
27
|
+
action: "tools",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: "/todos",
|
|
31
|
+
description: "Display current todo list",
|
|
32
|
+
action: "todos",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "/clear-todos",
|
|
36
|
+
description: "Clear all todos",
|
|
37
|
+
action: "clear-todos",
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
name: "/context",
|
|
41
|
+
description: "Show file context from current directory",
|
|
42
|
+
shortcut: "c",
|
|
43
|
+
action: "context",
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: "/clear",
|
|
47
|
+
description: "Clear chat history",
|
|
48
|
+
action: "clear",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "/api-key",
|
|
52
|
+
description: "Update your Groq API key",
|
|
53
|
+
action: "api-key",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: "/exit",
|
|
57
|
+
description: "Exit the application",
|
|
58
|
+
shortcut: "q",
|
|
59
|
+
action: "exit",
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
function formatCommandChoice(cmd) {
|
|
63
|
+
const shortcut = cmd.shortcut ? chalk_1.default.dim(` (${cmd.shortcut})`) : "";
|
|
64
|
+
return `${chalk_1.default.cyan(cmd.name)}${shortcut} ${chalk_1.default.dim("─")} ${cmd.description}`;
|
|
65
|
+
}
|
|
66
|
+
async function showSlashCommandMenu() {
|
|
67
|
+
try {
|
|
68
|
+
const answer = await (0, search_1.default)({
|
|
69
|
+
message: "Command",
|
|
70
|
+
source: async (input) => {
|
|
71
|
+
const searchTerm = (input || "").toLowerCase().replace(/^\//, "");
|
|
72
|
+
return exports.SLASH_COMMANDS.filter((cmd) => {
|
|
73
|
+
if (!searchTerm)
|
|
74
|
+
return true;
|
|
75
|
+
return (cmd.name.toLowerCase().includes(searchTerm) ||
|
|
76
|
+
cmd.description.toLowerCase().includes(searchTerm) ||
|
|
77
|
+
cmd.shortcut?.toLowerCase() === searchTerm);
|
|
78
|
+
}).map((cmd) => ({
|
|
79
|
+
name: formatCommandChoice(cmd),
|
|
80
|
+
value: cmd.action,
|
|
81
|
+
description: cmd.description,
|
|
82
|
+
}));
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
return answer;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// User cancelled (Ctrl+C)
|
|
89
|
+
if (error.message?.includes("cancelled") || error.name === "ExitPromptError") {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prab-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
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": {
|
|
@@ -49,6 +49,8 @@
|
|
|
49
49
|
"LICENSE"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
+
"@inquirer/search": "^4.1.0",
|
|
53
|
+
"@inquirer/select": "^5.0.4",
|
|
52
54
|
"@langchain/core": "^1.1.11",
|
|
53
55
|
"@langchain/groq": "^1.0.2",
|
|
54
56
|
"@langchain/openai": "^1.2.2",
|