prab-cli 1.0.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/LICENSE +15 -0
- package/README.md +272 -0
- package/dist/index.js +374 -0
- package/dist/lib/chat-handler.js +219 -0
- package/dist/lib/config.js +156 -0
- package/dist/lib/context.js +44 -0
- package/dist/lib/groq-models.js +53 -0
- package/dist/lib/groq.js +33 -0
- package/dist/lib/models/groq-provider.js +82 -0
- package/dist/lib/models/provider.js +10 -0
- package/dist/lib/models/registry.js +101 -0
- package/dist/lib/safety.js +109 -0
- package/dist/lib/tools/base.js +115 -0
- package/dist/lib/tools/executor.js +127 -0
- package/dist/lib/tools/file-tools.js +283 -0
- package/dist/lib/tools/git-tools.js +280 -0
- package/dist/lib/tools/shell-tools.js +73 -0
- package/dist/lib/tools/todo-tool.js +105 -0
- package/dist/lib/tracker.js +314 -0
- package/dist/lib/ui.js +578 -0
- package/dist/log-viewer.js +374 -0
- package/dist/types/index.js +5 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Prabhanjan Sharma
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# Prab CLI
|
|
2
|
+
|
|
3
|
+
An AI-powered coding assistant for your terminal. Built with Groq's lightning-fast LLMs, featuring autonomous tool execution, syntax-highlighted output, and seamless git integration.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **AI-Powered Coding Assistant** - Chat with AI that understands your codebase
|
|
11
|
+
- **Autonomous Tool Execution** - AI can read, write, and edit files directly
|
|
12
|
+
- **Git Integration** - Built-in git status, diff, commit, push, and more
|
|
13
|
+
- **Syntax Highlighting** - Beautiful colored output for code blocks and diffs
|
|
14
|
+
- **Multiple Models** - Switch between Groq models on the fly
|
|
15
|
+
- **Task Tracking** - Built-in todo management for complex tasks
|
|
16
|
+
- **Safety Checks** - Confirmation prompts for destructive operations
|
|
17
|
+
- **Session Logging** - Debug and track all AI interactions
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g prab-cli
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
1. **Get a Groq API Key** from [console.groq.com](https://console.groq.com)
|
|
28
|
+
|
|
29
|
+
2. **Configure your API key:**
|
|
30
|
+
```bash
|
|
31
|
+
groq-cli config
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
3. **Start chatting:**
|
|
35
|
+
```bash
|
|
36
|
+
groq-cli
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Interactive Mode
|
|
42
|
+
|
|
43
|
+
Simply run `groq-cli` to start an interactive session:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
groq-cli
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
You'll see the welcome banner and can start chatting with the AI:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
____ __ ________ ____
|
|
53
|
+
/ __ \_________ _/ /_ / ____/ / / _/
|
|
54
|
+
/ /_/ / ___/ __ `/ __ \ / / / / / /
|
|
55
|
+
/ ____/ / / /_/ / /_/ / / /___/ /____/ /
|
|
56
|
+
/_/ /_/ \__,_/_.___/ \____/_____/___/
|
|
57
|
+
|
|
58
|
+
Active Model: llama-3.3-70b-versatile
|
|
59
|
+
Available Tools: 14
|
|
60
|
+
|
|
61
|
+
> Help me refactor the authentication module
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Slash Commands
|
|
65
|
+
|
|
66
|
+
Type `/` during a session to access the command menu:
|
|
67
|
+
|
|
68
|
+
| Command | Description |
|
|
69
|
+
|---------|-------------|
|
|
70
|
+
| `/` | Open command menu |
|
|
71
|
+
| `/exit` | Exit the CLI |
|
|
72
|
+
| `/clear` | Clear chat history |
|
|
73
|
+
| `/context` | Show loaded file context |
|
|
74
|
+
| `/tools` | List available tools |
|
|
75
|
+
| `/todos` | Show current todo list |
|
|
76
|
+
|
|
77
|
+
### Command Menu Options
|
|
78
|
+
|
|
79
|
+
1. **Select Model** - Switch between available Groq models
|
|
80
|
+
2. **Usage** - View current model and session stats
|
|
81
|
+
3. **Tools** - List all available tools
|
|
82
|
+
4. **Todos** - View task list
|
|
83
|
+
5. **Clear Todos** - Reset task list
|
|
84
|
+
6. **Context** - Show file context
|
|
85
|
+
7. **Clear History** - Reset conversation
|
|
86
|
+
8. **API Key** - Update your API key
|
|
87
|
+
9. **Exit** - Quit the CLI
|
|
88
|
+
|
|
89
|
+
## Available Tools
|
|
90
|
+
|
|
91
|
+
The AI has access to these tools for autonomous coding:
|
|
92
|
+
|
|
93
|
+
### File Operations
|
|
94
|
+
| Tool | Description |
|
|
95
|
+
|------|-------------|
|
|
96
|
+
| `read_file` | Read file contents with line numbers |
|
|
97
|
+
| `write_file` | Create or overwrite files |
|
|
98
|
+
| `edit_file` | Make targeted edits to existing files |
|
|
99
|
+
| `glob` | Find files matching patterns |
|
|
100
|
+
| `grep` | Search file contents with regex |
|
|
101
|
+
|
|
102
|
+
### Git Operations
|
|
103
|
+
| Tool | Description |
|
|
104
|
+
|------|-------------|
|
|
105
|
+
| `git_status` | Show working tree status |
|
|
106
|
+
| `git_diff` | Show changes between commits |
|
|
107
|
+
| `git_log` | View commit history |
|
|
108
|
+
| `git_add` | Stage files for commit |
|
|
109
|
+
| `git_commit` | Create a commit |
|
|
110
|
+
| `git_branch` | List or create branches |
|
|
111
|
+
| `git_push` | Push commits to remote |
|
|
112
|
+
|
|
113
|
+
### System
|
|
114
|
+
| Tool | Description |
|
|
115
|
+
|------|-------------|
|
|
116
|
+
| `bash` | Execute shell commands |
|
|
117
|
+
| `manage_todos` | Track tasks and progress |
|
|
118
|
+
|
|
119
|
+
## Colorized Output
|
|
120
|
+
|
|
121
|
+
The CLI provides rich, colorized output for better readability:
|
|
122
|
+
|
|
123
|
+
### Git Diff
|
|
124
|
+
- Added lines in **green**
|
|
125
|
+
- Removed lines in **red**
|
|
126
|
+
- Hunk headers in **cyan**
|
|
127
|
+
- File headers in **bold**
|
|
128
|
+
|
|
129
|
+
### Code Blocks
|
|
130
|
+
- Keywords highlighted in **magenta**
|
|
131
|
+
- Strings in **green**
|
|
132
|
+
- Numbers in **yellow**
|
|
133
|
+
- Comments in **gray**
|
|
134
|
+
- Function calls in **cyan**
|
|
135
|
+
|
|
136
|
+
### Markdown
|
|
137
|
+
- Headers in **cyan bold**
|
|
138
|
+
- Inline code with **gray background**
|
|
139
|
+
- Bullet points with **yellow** markers
|
|
140
|
+
- Bold and italic text styling
|
|
141
|
+
|
|
142
|
+
## Configuration
|
|
143
|
+
|
|
144
|
+
### API Key
|
|
145
|
+
|
|
146
|
+
Set your Groq API key:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# Interactive prompt
|
|
150
|
+
groq-cli config
|
|
151
|
+
|
|
152
|
+
# Or directly
|
|
153
|
+
groq-cli config YOUR_API_KEY
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Reset API Key
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
groq-cli reset
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Model Management
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
groq-cli model
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Options:
|
|
169
|
+
- List available models
|
|
170
|
+
- Show current model
|
|
171
|
+
- Switch to a different model
|
|
172
|
+
|
|
173
|
+
## Supported Models
|
|
174
|
+
|
|
175
|
+
The CLI supports all Groq models including:
|
|
176
|
+
|
|
177
|
+
- `llama-3.3-70b-versatile` (default)
|
|
178
|
+
- `llama-3.1-70b-versatile`
|
|
179
|
+
- `llama-3.1-8b-instant`
|
|
180
|
+
- `mixtral-8x7b-32768`
|
|
181
|
+
- `gemma2-9b-it`
|
|
182
|
+
- And more...
|
|
183
|
+
|
|
184
|
+
Models are fetched dynamically from the Groq API.
|
|
185
|
+
|
|
186
|
+
## Session Logging
|
|
187
|
+
|
|
188
|
+
Debug logs are stored in `~/.prab-cli/logs/`. View them with:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# View latest log
|
|
192
|
+
npm run log
|
|
193
|
+
|
|
194
|
+
# List all logs
|
|
195
|
+
npm run log:list
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Examples
|
|
199
|
+
|
|
200
|
+
### Read and Edit a File
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
> Read the package.json and update the version to 2.0.0
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The AI will:
|
|
207
|
+
1. Use `read_file` to view package.json
|
|
208
|
+
2. Use `edit_file` to update the version
|
|
209
|
+
3. Show you the diff of changes
|
|
210
|
+
|
|
211
|
+
### Git Workflow
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
> Check the git status and commit all changes with a descriptive message
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The AI will:
|
|
218
|
+
1. Run `git_status` to see changes
|
|
219
|
+
2. Use `git_add` to stage files
|
|
220
|
+
3. Create a commit with `git_commit`
|
|
221
|
+
|
|
222
|
+
### Code Search
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
> Find all files that import the 'express' module
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
The AI will use `grep` to search for import statements.
|
|
229
|
+
|
|
230
|
+
## Safety Features
|
|
231
|
+
|
|
232
|
+
- **Confirmation Prompts** - Destructive operations require approval
|
|
233
|
+
- **Session Memory** - Remember choices for similar operations
|
|
234
|
+
- **Read-Only by Default** - Tools like `read_file` and `git_status` run without confirmation
|
|
235
|
+
|
|
236
|
+
## Requirements
|
|
237
|
+
|
|
238
|
+
- Node.js 18+
|
|
239
|
+
- npm or yarn
|
|
240
|
+
- Groq API key
|
|
241
|
+
|
|
242
|
+
## Development
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Clone the repo
|
|
246
|
+
git clone https://github.com/prab002/prab-cli.git
|
|
247
|
+
cd prab-cli
|
|
248
|
+
|
|
249
|
+
# Install dependencies
|
|
250
|
+
npm install
|
|
251
|
+
|
|
252
|
+
# Run in development mode
|
|
253
|
+
npm run dev
|
|
254
|
+
|
|
255
|
+
# Build
|
|
256
|
+
npm run build
|
|
257
|
+
|
|
258
|
+
# Run production build
|
|
259
|
+
npm start
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## License
|
|
263
|
+
|
|
264
|
+
ISC
|
|
265
|
+
|
|
266
|
+
## Author
|
|
267
|
+
|
|
268
|
+
Prabhanjan Sharma
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
Built with [Groq](https://groq.com) | [LangChain](https://langchain.com) | [Chalk](https://github.com/chalk/chalk)
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
9
|
+
const config_1 = require("./lib/config");
|
|
10
|
+
const context_1 = require("./lib/context");
|
|
11
|
+
const ui_1 = require("./lib/ui");
|
|
12
|
+
const config_2 = require("./lib/config");
|
|
13
|
+
const ora_1 = __importDefault(require("ora"));
|
|
14
|
+
// Import tool system
|
|
15
|
+
const base_1 = require("./lib/tools/base");
|
|
16
|
+
const executor_1 = require("./lib/tools/executor");
|
|
17
|
+
const file_tools_1 = require("./lib/tools/file-tools");
|
|
18
|
+
const shell_tools_1 = require("./lib/tools/shell-tools");
|
|
19
|
+
const git_tools_1 = require("./lib/tools/git-tools");
|
|
20
|
+
const todo_tool_1 = require("./lib/tools/todo-tool");
|
|
21
|
+
// Import model system
|
|
22
|
+
const groq_provider_1 = require("./lib/models/groq-provider");
|
|
23
|
+
const registry_1 = require("./lib/models/registry");
|
|
24
|
+
const groq_models_1 = require("./lib/groq-models");
|
|
25
|
+
// Import chat handler and safety
|
|
26
|
+
const chat_handler_1 = require("./lib/chat-handler");
|
|
27
|
+
const safety_1 = require("./lib/safety");
|
|
28
|
+
const tracker_1 = require("./lib/tracker");
|
|
29
|
+
// Cache for available models
|
|
30
|
+
let cachedModels = [];
|
|
31
|
+
const program = new commander_1.Command();
|
|
32
|
+
program
|
|
33
|
+
.name("prab-cli")
|
|
34
|
+
.description("An AI coding assistant with autonomous tool capabilities")
|
|
35
|
+
.version("2.0.0");
|
|
36
|
+
// Config command
|
|
37
|
+
program
|
|
38
|
+
.command("config [key]")
|
|
39
|
+
.description("Set your Groq API Key")
|
|
40
|
+
.action(async (key) => {
|
|
41
|
+
if (key) {
|
|
42
|
+
(0, config_1.setApiKey)(key.trim());
|
|
43
|
+
ui_1.log.success("API Key saved successfully!");
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const { inputKey } = await inquirer_1.default.prompt([
|
|
47
|
+
{
|
|
48
|
+
type: "password",
|
|
49
|
+
name: "inputKey",
|
|
50
|
+
message: "Enter your Groq API Key:",
|
|
51
|
+
mask: "*",
|
|
52
|
+
},
|
|
53
|
+
]);
|
|
54
|
+
(0, config_1.setApiKey)(inputKey.trim());
|
|
55
|
+
ui_1.log.success("API Key saved successfully!");
|
|
56
|
+
});
|
|
57
|
+
// Reset command
|
|
58
|
+
program
|
|
59
|
+
.command("reset")
|
|
60
|
+
.description("Clear your stored API Key")
|
|
61
|
+
.action(() => {
|
|
62
|
+
(0, config_1.clearApiKey)();
|
|
63
|
+
ui_1.log.success("API Key cleared!");
|
|
64
|
+
});
|
|
65
|
+
// Model management commands
|
|
66
|
+
program
|
|
67
|
+
.command("model")
|
|
68
|
+
.description("Manage AI models")
|
|
69
|
+
.action(async () => {
|
|
70
|
+
const { action } = await inquirer_1.default.prompt([
|
|
71
|
+
{
|
|
72
|
+
type: "list",
|
|
73
|
+
name: "action",
|
|
74
|
+
message: "Model Management:",
|
|
75
|
+
choices: [
|
|
76
|
+
{ name: "List available models", value: "list" },
|
|
77
|
+
{ name: "Show current model", value: "current" },
|
|
78
|
+
{ name: "Switch model", value: "switch" },
|
|
79
|
+
{ name: "Cancel", value: "cancel" },
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
]);
|
|
83
|
+
if (action === "list") {
|
|
84
|
+
console.log("\nAvailable Models:\n");
|
|
85
|
+
console.log((0, registry_1.getModelList)());
|
|
86
|
+
}
|
|
87
|
+
else if (action === "current") {
|
|
88
|
+
const config = (0, config_1.getModelConfig)();
|
|
89
|
+
ui_1.log.info(`Current model: ${config.modelId}`);
|
|
90
|
+
ui_1.log.info(`Temperature: ${config.temperature}`);
|
|
91
|
+
}
|
|
92
|
+
else if (action === "switch") {
|
|
93
|
+
const { modelId } = await inquirer_1.default.prompt([
|
|
94
|
+
{
|
|
95
|
+
type: "input",
|
|
96
|
+
name: "modelId",
|
|
97
|
+
message: "Enter model ID:",
|
|
98
|
+
},
|
|
99
|
+
]);
|
|
100
|
+
const validation = (0, registry_1.validateModelId)(modelId);
|
|
101
|
+
if (validation.valid) {
|
|
102
|
+
(0, config_1.setActiveModel)(modelId);
|
|
103
|
+
ui_1.log.success(`Switched to model: ${modelId}`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
ui_1.log.error(validation.error || "Invalid model");
|
|
107
|
+
if (validation.suggested) {
|
|
108
|
+
ui_1.log.info(`Did you mean: ${validation.suggested}?`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
// Main interactive mode
|
|
114
|
+
program.action(async () => {
|
|
115
|
+
// Check API Key
|
|
116
|
+
let apiKey = (0, config_1.getApiKey)();
|
|
117
|
+
if (!apiKey) {
|
|
118
|
+
ui_1.log.warning("No API Key found.");
|
|
119
|
+
const { key } = await inquirer_1.default.prompt([
|
|
120
|
+
{
|
|
121
|
+
type: "password",
|
|
122
|
+
name: "key",
|
|
123
|
+
message: "Please enter your Groq API Key to get started:",
|
|
124
|
+
mask: "*",
|
|
125
|
+
},
|
|
126
|
+
]);
|
|
127
|
+
(0, config_1.setApiKey)(key.trim());
|
|
128
|
+
apiKey = key.trim();
|
|
129
|
+
}
|
|
130
|
+
// Initialize tool registry
|
|
131
|
+
const toolRegistry = new base_1.ToolRegistry();
|
|
132
|
+
toolRegistry.register(new file_tools_1.ReadFileTool());
|
|
133
|
+
toolRegistry.register(new file_tools_1.WriteFileTool());
|
|
134
|
+
toolRegistry.register(new file_tools_1.EditFileTool());
|
|
135
|
+
toolRegistry.register(new file_tools_1.GlobTool());
|
|
136
|
+
toolRegistry.register(new file_tools_1.GrepTool());
|
|
137
|
+
toolRegistry.register(new shell_tools_1.BashTool());
|
|
138
|
+
toolRegistry.register(new git_tools_1.GitStatusTool());
|
|
139
|
+
toolRegistry.register(new git_tools_1.GitAddTool());
|
|
140
|
+
toolRegistry.register(new git_tools_1.GitDiffTool());
|
|
141
|
+
toolRegistry.register(new git_tools_1.GitLogTool());
|
|
142
|
+
toolRegistry.register(new git_tools_1.GitCommitTool());
|
|
143
|
+
toolRegistry.register(new git_tools_1.GitBranchTool());
|
|
144
|
+
toolRegistry.register(new git_tools_1.GitPushTool());
|
|
145
|
+
toolRegistry.register(new todo_tool_1.TodoTool());
|
|
146
|
+
// Initialize safety checker and tool executor
|
|
147
|
+
const safetyChecker = new safety_1.SafetyChecker();
|
|
148
|
+
const toolExecutor = new executor_1.ToolExecutor(toolRegistry, safetyChecker);
|
|
149
|
+
// Initialize model provider
|
|
150
|
+
const modelConfig = (0, config_1.getModelConfig)();
|
|
151
|
+
const modelProvider = new groq_provider_1.GroqProvider(modelConfig.modelId, modelConfig.temperature);
|
|
152
|
+
try {
|
|
153
|
+
modelProvider.initialize(apiKey, modelConfig.modelId);
|
|
154
|
+
tracker_1.tracker.modelInit(modelConfig.modelId, "groq", true);
|
|
155
|
+
tracker_1.tracker.sessionStart(modelConfig.modelId, toolRegistry.count());
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
ui_1.log.error("Failed to initialize model.");
|
|
159
|
+
tracker_1.tracker.modelInit(modelConfig.modelId, "groq", false, e.message);
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
// Display banner
|
|
163
|
+
(0, ui_1.banner)(modelConfig.modelId, toolRegistry.count());
|
|
164
|
+
// Context Gathering
|
|
165
|
+
const spinner = (0, ora_1.default)("Checking context...").start();
|
|
166
|
+
const isRepo = await (0, context_1.isGitRepo)();
|
|
167
|
+
let contextMessage = "";
|
|
168
|
+
if (isRepo) {
|
|
169
|
+
spinner.text = "Git repository detected. Gathering file structure...";
|
|
170
|
+
const files = await (0, context_1.getFileTree)();
|
|
171
|
+
contextMessage = `\n\nCurrent Working Directory Context:\nFile List:\n${files.join("\n")}`;
|
|
172
|
+
spinner.succeed(`Context loaded (${files.length} files detected).`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
spinner.succeed("No Git repository detected. Running in standalone mode.");
|
|
176
|
+
}
|
|
177
|
+
// Initialize chat handler
|
|
178
|
+
const chatHandler = new chat_handler_1.ChatHandler(toolRegistry, toolExecutor, modelProvider, contextMessage);
|
|
179
|
+
ui_1.log.info('Type "/" for commands menu, or start chatting!');
|
|
180
|
+
// Display any existing todos
|
|
181
|
+
const session = (0, config_2.getSessionData)();
|
|
182
|
+
if (session.todos && session.todos.length > 0) {
|
|
183
|
+
(0, ui_1.showTodoList)(session.todos);
|
|
184
|
+
}
|
|
185
|
+
// Chat Loop
|
|
186
|
+
while (true) {
|
|
187
|
+
const { userInput } = await inquirer_1.default.prompt([
|
|
188
|
+
{
|
|
189
|
+
type: "input",
|
|
190
|
+
name: "userInput",
|
|
191
|
+
message: ">",
|
|
192
|
+
},
|
|
193
|
+
]);
|
|
194
|
+
// Handle Slash Commands Menu
|
|
195
|
+
if (userInput.trim() === "/") {
|
|
196
|
+
const currentModel = modelProvider.modelId;
|
|
197
|
+
console.log("\n┌────────────────────────────────────────┐");
|
|
198
|
+
console.log("│ AVAILABLE COMMANDS │");
|
|
199
|
+
console.log("└────────────────────────────────────────┘\n");
|
|
200
|
+
const { action } = await inquirer_1.default.prompt([
|
|
201
|
+
{
|
|
202
|
+
type: "list",
|
|
203
|
+
name: "action",
|
|
204
|
+
message: "Choose an option:",
|
|
205
|
+
choices: [
|
|
206
|
+
"1. Select Model",
|
|
207
|
+
"2. Usage",
|
|
208
|
+
"3. Tools",
|
|
209
|
+
"4. Todos",
|
|
210
|
+
"5. Clear Todos",
|
|
211
|
+
"6. Context",
|
|
212
|
+
"7. Clear History",
|
|
213
|
+
"8. API Key",
|
|
214
|
+
"9. Exit",
|
|
215
|
+
],
|
|
216
|
+
},
|
|
217
|
+
]);
|
|
218
|
+
// Select Model - Toggle between different models
|
|
219
|
+
if (action === "1. Select Model") {
|
|
220
|
+
// Fetch models from Groq API if not cached
|
|
221
|
+
if (cachedModels.length === 0) {
|
|
222
|
+
const spinner = (0, ora_1.default)("Fetching available models from Groq...").start();
|
|
223
|
+
cachedModels = await (0, groq_models_1.fetchGroqModels)(apiKey);
|
|
224
|
+
spinner.succeed(`Found ${cachedModels.length} models`);
|
|
225
|
+
}
|
|
226
|
+
// Group models by owner
|
|
227
|
+
const grouped = (0, groq_models_1.groupModelsByOwner)(cachedModels);
|
|
228
|
+
const modelChoices = [];
|
|
229
|
+
// Build choices grouped by owner
|
|
230
|
+
for (const [owner, models] of grouped) {
|
|
231
|
+
modelChoices.push(new inquirer_1.default.Separator(`─── ${owner} ───`));
|
|
232
|
+
for (const model of models) {
|
|
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,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const { selectedModel } = await inquirer_1.default.prompt([
|
|
243
|
+
{
|
|
244
|
+
type: "list",
|
|
245
|
+
name: "selectedModel",
|
|
246
|
+
message: `Select a model (current: ${currentModel}):`,
|
|
247
|
+
choices: modelChoices,
|
|
248
|
+
pageSize: 15,
|
|
249
|
+
loop: false,
|
|
250
|
+
},
|
|
251
|
+
]);
|
|
252
|
+
if (selectedModel && selectedModel !== currentModel) {
|
|
253
|
+
const oldModel = currentModel;
|
|
254
|
+
(0, config_1.setActiveModel)(selectedModel);
|
|
255
|
+
modelProvider.setModel(selectedModel);
|
|
256
|
+
ui_1.log.success(`Switched to model: ${selectedModel}`);
|
|
257
|
+
tracker_1.tracker.modelSwitch(oldModel, selectedModel, true);
|
|
258
|
+
}
|
|
259
|
+
else if (selectedModel === currentModel) {
|
|
260
|
+
ui_1.log.info(`Already using ${selectedModel}`);
|
|
261
|
+
}
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
// Usage - Show model usage and stats
|
|
265
|
+
if (action === "2. Usage") {
|
|
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();
|
|
275
|
+
}
|
|
276
|
+
const modelInfo = cachedModels.find((m) => m.id === currentModel);
|
|
277
|
+
if (modelInfo) {
|
|
278
|
+
console.log(` Provider: ${modelInfo.owned_by}`);
|
|
279
|
+
console.log(` Context: ${(0, groq_models_1.formatContextWindow)(modelInfo.context_window)} tokens`);
|
|
280
|
+
console.log(` Status: ${modelInfo.active ? "Active" : "Inactive"}`);
|
|
281
|
+
}
|
|
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
|
+
}
|
|
367
|
+
ui_1.log.warning(`Unknown command: ${cmd}. Type "/" for menu.`);
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
// Process user input with chat handler
|
|
371
|
+
await chatHandler.processUserInput(userInput);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
program.parse(process.argv);
|