prituscode 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/README.md +79 -0
- package/package.json +17 -0
- package/prituscode.js +359 -0
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# PRITUS CODE CLI
|
|
2
|
+
|
|
3
|
+
**Terminal-based AI coding assistant.** Local Vision Intelligence in your terminal.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install globally
|
|
9
|
+
npm install -g prituscode
|
|
10
|
+
|
|
11
|
+
# Or run directly with npx (no install needed)
|
|
12
|
+
npx prituscode
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
### Interactive mode
|
|
18
|
+
```bash
|
|
19
|
+
prituscode
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### One-shot mode
|
|
23
|
+
```bash
|
|
24
|
+
prituscode "build a responsive navbar with Tailwind"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Custom endpoint
|
|
28
|
+
```bash
|
|
29
|
+
prituscode --endpoint https://your-pritus-deployment.com
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Select model tier
|
|
33
|
+
```bash
|
|
34
|
+
prituscode --model thinking
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Commands (interactive mode)
|
|
38
|
+
|
|
39
|
+
| Command | Description |
|
|
40
|
+
|---------|-------------|
|
|
41
|
+
| `/help` | Show available commands |
|
|
42
|
+
| `/clear` | Clear conversation history |
|
|
43
|
+
| `/model` | Switch model tier (`flash` / `pro` / `thinking`) |
|
|
44
|
+
| `/status` | Show connection status |
|
|
45
|
+
| `/exit` | Exit the CLI |
|
|
46
|
+
|
|
47
|
+
## Environment Variables
|
|
48
|
+
|
|
49
|
+
| Variable | Default | Description |
|
|
50
|
+
|----------|---------|-------------|
|
|
51
|
+
| `PRITUS_API_URL` | `https://pritusai.netlify.app` | API endpoint |
|
|
52
|
+
| `PRITUS_MODEL` | `pro` | Default model tier |
|
|
53
|
+
|
|
54
|
+
## Run without installing
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Clone and run directly
|
|
58
|
+
git clone https://github.com/sarthaksahoo/pritus-ai
|
|
59
|
+
cd pritus-ai/cli
|
|
60
|
+
node prituscode.js
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Publish to npm
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm login # log in to your npm account
|
|
67
|
+
cd cli
|
|
68
|
+
npm publish
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
After publishing, anyone can run `npx prituscode` globally.
|
|
72
|
+
|
|
73
|
+
## Requirements
|
|
74
|
+
|
|
75
|
+
- Node.js 18+ (for built-in `fetch`)
|
|
76
|
+
|
|
77
|
+
## License
|
|
78
|
+
|
|
79
|
+
MIT © Sarthak Sahoo
|
package/package.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "prituscode",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Terminal-based AI coding agent CLI",
|
|
5
|
+
"main": "prituscode.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"prituscode": "./prituscode.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node ./prituscode.js"
|
|
11
|
+
},
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=18.0.0"
|
|
14
|
+
},
|
|
15
|
+
"author": "",
|
|
16
|
+
"license": "ISC"
|
|
17
|
+
}
|
package/prituscode.js
ADDED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const readline = require('readline');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
8
|
+
|
|
9
|
+
// --- ANSI COLORS & STYLES ---
|
|
10
|
+
const c = {
|
|
11
|
+
rst: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
|
|
12
|
+
black: '\x1b[30m', red: '\x1b[31m', green: '\x1b[32m',
|
|
13
|
+
yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m',
|
|
14
|
+
cyan: '\x1b[36m', white: '\x1b[37m',
|
|
15
|
+
bgMagenta: '\x1b[45m', bgBlue: '\x1b[44m'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// --- CONFIG & STATE ---
|
|
19
|
+
const args = process.argv.slice(2);
|
|
20
|
+
let config = {
|
|
21
|
+
tier: 'pro',
|
|
22
|
+
endpoint: 'https://pritusai.vercel.app/api/pritus/chat',
|
|
23
|
+
oneShotPrompt: ''
|
|
24
|
+
};
|
|
25
|
+
const messages = [];
|
|
26
|
+
|
|
27
|
+
// Parse flags
|
|
28
|
+
for (let i = 0; i < args.length; i++) {
|
|
29
|
+
if (args[i] === '--endpoint' && args[i + 1]) {
|
|
30
|
+
config.endpoint = args[++i];
|
|
31
|
+
} else if (args[i] === '--model' && args[i + 1]) {
|
|
32
|
+
config.tier = args[++i];
|
|
33
|
+
} else if (!args[i].startsWith('--')) {
|
|
34
|
+
config.oneShotPrompt = args.slice(i).join(' ');
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// --- SYSTEM PROMPT ---
|
|
40
|
+
const AGENT_SYSTEM = `
|
|
41
|
+
You are PRITUS CODE, an elite terminal-based AI coding agent.
|
|
42
|
+
When generating or modifying code, you must ACT as an agent. Use the exact format below:
|
|
43
|
+
|
|
44
|
+
THINKING: <one sentence reasoning about what you will do>
|
|
45
|
+
CREATE_FILE: <filepath>
|
|
46
|
+
<entire file content here>
|
|
47
|
+
DONE: <short summary of what was done>
|
|
48
|
+
|
|
49
|
+
If the user is just asking a question and no files need to be written, simply reply conversationally without those tags. Do not reveal your underlying model name under any circumstance.
|
|
50
|
+
`;
|
|
51
|
+
messages.push({ role: 'system', content: AGENT_SYSTEM });
|
|
52
|
+
|
|
53
|
+
// --- UTILS ---
|
|
54
|
+
const sleep = ms => new Promise(r => setTimeout(r, ms));
|
|
55
|
+
|
|
56
|
+
const rl = readline.createInterface({
|
|
57
|
+
input: process.stdin,
|
|
58
|
+
output: process.stdout,
|
|
59
|
+
prompt: `${c.magenta}${c.bold}> ${c.rst}`
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const ask = query => new Promise(resolve => {
|
|
63
|
+
rl.question(query, resolve);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// --- UI COMPONENTS ---
|
|
67
|
+
function clearConsole() {
|
|
68
|
+
process.stdout.write('\x1B[2J\x1B[0f');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function printLogo() {
|
|
72
|
+
// Blue to Magenta ANSI 256 gradient approximation
|
|
73
|
+
const d1 = '\x1b[38;5;33m';
|
|
74
|
+
const d2 = '\x1b[38;5;39m';
|
|
75
|
+
const d3 = '\x1b[38;5;135m';
|
|
76
|
+
const d4 = '\x1b[38;5;165m';
|
|
77
|
+
const d5 = '\x1b[38;5;199m';
|
|
78
|
+
|
|
79
|
+
console.log(`
|
|
80
|
+
${d1} /\\ ${c.bold}██████╗ ██████╗ ██╗████████╗██╗ ██╗███████╗${c.rst}
|
|
81
|
+
${d2} / \\ ${c.bold}██╔══██╗██╔══██╗██║╚══██╔══╝██║ ██║██╔════╝${c.rst}
|
|
82
|
+
${d3} /____\\ ${c.bold}██████╔╝██████╔╝██║ ██║ ██║ ██║███████╗${c.rst}
|
|
83
|
+
${d4} \\ / ${c.bold}██╔═══╝ ██╔══██╗██║ ██║ ██║ ██║╚════██║${c.rst}
|
|
84
|
+
${d5} \\ / ${c.bold}██║ ██║ ██║██║ ██║ ╚██████╔╝███████║${c.rst}
|
|
85
|
+
${c.magenta} \\/ ${c.bold}╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝${c.rst}
|
|
86
|
+
${c.dim}v1.0.0${c.rst}
|
|
87
|
+
`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function printWelcomeBox() {
|
|
91
|
+
const cwd = process.cwd();
|
|
92
|
+
const boxWidth = Math.max(60, cwd.length + 20);
|
|
93
|
+
const line = '─'.repeat(boxWidth - 2);
|
|
94
|
+
console.log(`${c.magenta}┌${line}┐${c.rst}`);
|
|
95
|
+
console.log(`${c.magenta}│${c.rst} ${c.bold}Welcome to PRITUS CODE${c.rst}`.padEnd(boxWidth + c.magenta.length + c.rst.length + c.bold.length + c.rst.length - 1) + `${c.magenta}│${c.rst}`);
|
|
96
|
+
console.log(`${c.magenta}│${c.rst} ${c.dim}Type /help for commands, @filename to attach files${c.rst}`.padEnd(boxWidth + c.magenta.length + c.rst.length + c.dim.length + c.rst.length - 1) + `${c.magenta}│${c.rst}`);
|
|
97
|
+
console.log(`${c.magenta}│${c.rst} ${c.cyan}Workspace: ${cwd}${c.rst}`.padEnd(boxWidth + c.magenta.length + c.rst.length + c.cyan.length + c.rst.length - 1) + `${c.magenta}│${c.rst}`);
|
|
98
|
+
console.log(`${c.magenta}└${line}┘${c.rst}\n`);
|
|
99
|
+
|
|
100
|
+
console.log(`${c.bold}Tips:${c.rst}`);
|
|
101
|
+
console.log(` 1. Use @file to include file context`);
|
|
102
|
+
console.log(` 2. Type /model to switch intelligence tiers`);
|
|
103
|
+
console.log(` 3. Type /init to set up project instructions`);
|
|
104
|
+
console.log(` 4. Let the agent build files for you ${c.green}✓${c.rst}\n`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function printStatusBar() {
|
|
108
|
+
const cwd = path.basename(process.cwd());
|
|
109
|
+
const bar = `${c.bgMagenta}${c.white} ${cwd} ${c.rst} ${c.dim}model:${c.rst} ${config.tier} ${c.dim}| /help for menu${c.rst}`;
|
|
110
|
+
console.log(`\n${bar}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function startLoading(text = 'Thinking') {
|
|
114
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
115
|
+
let i = 0;
|
|
116
|
+
const interval = setInterval(() => {
|
|
117
|
+
process.stdout.write(`\r${c.magenta}${frames[i]}${c.rst} ${c.dim}${text}...${c.rst}`);
|
|
118
|
+
i = (i + 1) % frames.length;
|
|
119
|
+
}, 80);
|
|
120
|
+
return () => {
|
|
121
|
+
clearInterval(interval);
|
|
122
|
+
process.stdout.write('\r\x1b[K'); // clear line
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function streamText(text) {
|
|
127
|
+
const words = text.split(' ');
|
|
128
|
+
for (const word of words) {
|
|
129
|
+
process.stdout.write(word + ' ');
|
|
130
|
+
await sleep(20); // typing effect
|
|
131
|
+
}
|
|
132
|
+
console.log();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// --- COMMANDS & FEATURES ---
|
|
136
|
+
async function selectModel() {
|
|
137
|
+
console.log(`\n${c.bold}Select Model Tier:${c.rst}`);
|
|
138
|
+
console.log(` 1. Flash - Fast & lightweight`);
|
|
139
|
+
console.log(` 2. Pro - Balanced general use`);
|
|
140
|
+
console.log(` 3. Thinking - Deep reasoning`);
|
|
141
|
+
console.log(` 4. Ultra Code - Elite code generation`);
|
|
142
|
+
|
|
143
|
+
const choice = await ask(`\n${c.dim}Press 1-4 or Enter for Pro: ${c.rst}`);
|
|
144
|
+
switch(choice.trim()) {
|
|
145
|
+
case '1': config.tier = 'flash'; break;
|
|
146
|
+
case '3': config.tier = 'thinking'; break;
|
|
147
|
+
case '4': config.tier = 'code'; break;
|
|
148
|
+
case '2':
|
|
149
|
+
default: config.tier = 'pro'; break;
|
|
150
|
+
}
|
|
151
|
+
console.log(`${c.green}✓ Switched to ${config.tier} tier${c.rst}\n`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function processAtFiles(input) {
|
|
155
|
+
const fileRegex = /@([\w.\-\/]+)/g;
|
|
156
|
+
let modifiedInput = input;
|
|
157
|
+
let match;
|
|
158
|
+
let addedFiles = [];
|
|
159
|
+
|
|
160
|
+
while ((match = fileRegex.exec(input)) !== null) {
|
|
161
|
+
const filepath = match[1];
|
|
162
|
+
try {
|
|
163
|
+
const content = fs.readFileSync(filepath, 'utf-8');
|
|
164
|
+
modifiedInput += `\n\n[Context from ${filepath}]:\n\`\`\`\n${content}\n\`\`\``;
|
|
165
|
+
addedFiles.push(filepath);
|
|
166
|
+
} catch (e) {
|
|
167
|
+
console.log(`${c.red}⚠ Could not read @file: ${filepath}${c.rst}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (addedFiles.length > 0) {
|
|
171
|
+
console.log(`${c.dim}Attached: ${addedFiles.join(', ')}${c.rst}`);
|
|
172
|
+
}
|
|
173
|
+
return modifiedInput;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// --- AGENT PARSER ---
|
|
177
|
+
async function parseAndExecuteAgent(response) {
|
|
178
|
+
// Regex to extract blocks
|
|
179
|
+
const thinkingMatch = response.match(/THINKING:\s*(.*?)\n/i);
|
|
180
|
+
const doneMatch = response.match(/DONE:\s*(.*)/i);
|
|
181
|
+
const fileRegex = /CREATE_FILE:\s*(.*?)\n([\s\S]*?)(?=DONE:|CREATE_FILE:|$)/gi;
|
|
182
|
+
|
|
183
|
+
let isAgentic = false;
|
|
184
|
+
|
|
185
|
+
if (thinkingMatch) {
|
|
186
|
+
isAgentic = true;
|
|
187
|
+
console.log(`\n🤔 ${c.dim}${thinkingMatch[1].trim()}${c.rst}\n`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
let match;
|
|
191
|
+
let fileCount = 0;
|
|
192
|
+
while ((match = fileRegex.exec(response)) !== null) {
|
|
193
|
+
isAgentic = true;
|
|
194
|
+
const filepath = match[1].trim();
|
|
195
|
+
const content = match[2].trim();
|
|
196
|
+
|
|
197
|
+
console.log(`${c.cyan}┌─ CREATE: ${filepath}${c.rst}`);
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
const fullPath = path.resolve(process.cwd(), filepath);
|
|
201
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
202
|
+
fs.writeFileSync(fullPath, content);
|
|
203
|
+
console.log(`${c.cyan}└─ ${c.green}✓ Created successfully${c.rst}`);
|
|
204
|
+
fileCount++;
|
|
205
|
+
} catch (err) {
|
|
206
|
+
console.log(`${c.cyan}└─ ${c.red}✗ Failed: ${err.message}${c.rst}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (isAgentic && doneMatch) {
|
|
211
|
+
console.log(`\n${c.green}✓ Agent Finished:${c.rst} ${doneMatch[1].trim()} (${fileCount} files created)`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// If it didn't use the agent format, just stream it conversationally
|
|
215
|
+
if (!isAgentic) {
|
|
216
|
+
await streamText(response.trim());
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// --- API LAYER ---
|
|
221
|
+
async function handleChat(prompt) {
|
|
222
|
+
const finalPrompt = processAtFiles(prompt);
|
|
223
|
+
messages.push({ role: 'user', content: finalPrompt });
|
|
224
|
+
|
|
225
|
+
const stopLoading = await startLoading();
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
const res = await fetch(config.endpoint, {
|
|
229
|
+
method: 'POST',
|
|
230
|
+
headers: { 'Content-Type': 'application/json' },
|
|
231
|
+
body: JSON.stringify({
|
|
232
|
+
messages,
|
|
233
|
+
tier: config.tier,
|
|
234
|
+
plan: 'pro'
|
|
235
|
+
})
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
stopLoading();
|
|
239
|
+
|
|
240
|
+
if (!res.ok) {
|
|
241
|
+
throw new Error(`Status ${res.status}`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const data = await res.json();
|
|
245
|
+
// Assuming API returns { response: "..." } or similar
|
|
246
|
+
const reply = data.response || data.reply || data.content || data.message || (data.choices && data.choices[0].message.content);
|
|
247
|
+
|
|
248
|
+
if (!reply) {
|
|
249
|
+
console.log(`${c.red}⚠ Unexpected API response format.${c.rst}`);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
messages.push({ role: 'assistant', content: reply });
|
|
254
|
+
await parseAndExecuteAgent(reply);
|
|
255
|
+
|
|
256
|
+
} catch (error) {
|
|
257
|
+
stopLoading();
|
|
258
|
+
console.log(`${c.red}Pritus AI is suffering from heavy traffic right now. (Error: ${error.message})${c.rst}`);
|
|
259
|
+
// Remove the failed message so they can retry
|
|
260
|
+
messages.pop();
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// --- SIMULATED GOOGLE LOGIN ---
|
|
265
|
+
async function handleLogin() {
|
|
266
|
+
console.log(`\n${c.bold}Google Authentication${c.rst}`);
|
|
267
|
+
const code = Math.random().toString(36).substring(2, 10).toUpperCase();
|
|
268
|
+
console.log(`${c.dim}Please go to: ${c.white}https://google.com/device${c.rst}`);
|
|
269
|
+
console.log(`${c.dim}And enter this code: ${c.magenta}${c.bold}${code}${c.rst}\n`);
|
|
270
|
+
|
|
271
|
+
const stop = await startLoading('Waiting for authorization');
|
|
272
|
+
await sleep(4000); // Simulate waiting for external auth
|
|
273
|
+
stop();
|
|
274
|
+
|
|
275
|
+
const tokenPath = path.join(os.homedir(), '.prituscode_auth');
|
|
276
|
+
fs.writeFileSync(tokenPath, `mock_token_${Date.now()}`);
|
|
277
|
+
console.log(`${c.green}✓ Successfully logged in with Google!${c.rst}\n`);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
// --- MAIN REPL ---
|
|
282
|
+
async function main() {
|
|
283
|
+
if (config.oneShotPrompt) {
|
|
284
|
+
console.log(`${c.magenta}PRITUS CODE${c.rst} ${c.dim}> One-shot mode${c.rst}\n`);
|
|
285
|
+
await handleChat(config.oneShotPrompt);
|
|
286
|
+
process.exit(0);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
clearConsole();
|
|
290
|
+
printLogo();
|
|
291
|
+
printWelcomeBox();
|
|
292
|
+
|
|
293
|
+
// Auto-prompt for model on first run if in interactive mode
|
|
294
|
+
await selectModel();
|
|
295
|
+
printStatusBar();
|
|
296
|
+
|
|
297
|
+
rl.prompt();
|
|
298
|
+
|
|
299
|
+
rl.on('line', async (line) => {
|
|
300
|
+
const input = line.trim();
|
|
301
|
+
if (!input) {
|
|
302
|
+
rl.prompt();
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
switch (input.toLowerCase()) {
|
|
307
|
+
case '/exit':
|
|
308
|
+
case '/quit':
|
|
309
|
+
console.log(`${c.dim}Goodbye!${c.rst}`);
|
|
310
|
+
process.exit(0);
|
|
311
|
+
break;
|
|
312
|
+
case '/clear':
|
|
313
|
+
clearConsole();
|
|
314
|
+
messages.length = 1; // Keep system prompt
|
|
315
|
+
console.log(`${c.green}✓ Context cleared.${c.rst}`);
|
|
316
|
+
break;
|
|
317
|
+
case '/model':
|
|
318
|
+
await selectModel();
|
|
319
|
+
break;
|
|
320
|
+
case '/status':
|
|
321
|
+
console.log(`\n${c.bold}PRITUS STATUS${c.rst}`);
|
|
322
|
+
console.log(`Tier: ${c.magenta}${config.tier}${c.rst}`);
|
|
323
|
+
console.log(`Messages in context: ${messages.length - 1}`);
|
|
324
|
+
console.log(`Workspace: ${process.cwd()}\n`);
|
|
325
|
+
break;
|
|
326
|
+
case '/init':
|
|
327
|
+
fs.writeFileSync('PRITUS.md', '# PRITUS CODE Instructions\n\nAdd your custom project rules here. The agent will read this automatically if referenced.');
|
|
328
|
+
console.log(`${c.green}✓ Created PRITUS.md${c.rst}`);
|
|
329
|
+
break;
|
|
330
|
+
case '/login':
|
|
331
|
+
await handleLogin();
|
|
332
|
+
break;
|
|
333
|
+
case '/help':
|
|
334
|
+
console.log(`\n${c.bold}Commands:${c.rst}`);
|
|
335
|
+
console.log(` @filename Include file contents in your prompt`);
|
|
336
|
+
console.log(` /model Change AI tier (flash, pro, thinking, code)`);
|
|
337
|
+
console.log(` /init Create a PRITUS.md instruction file`);
|
|
338
|
+
console.log(` /clear Clear conversation history`);
|
|
339
|
+
console.log(` /status Show current agent status`);
|
|
340
|
+
console.log(` /login Authenticate with Google`);
|
|
341
|
+
console.log(` /exit Close PRITUS CODE\n`);
|
|
342
|
+
break;
|
|
343
|
+
default:
|
|
344
|
+
await handleChat(input);
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
printStatusBar();
|
|
349
|
+
rl.prompt();
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Handle interrupts gracefully
|
|
354
|
+
rl.on('SIGINT', () => {
|
|
355
|
+
console.log(`\n${c.dim}Operation cancelled. Type /exit to quit.${c.rst}`);
|
|
356
|
+
rl.prompt();
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
main().catch(console.error);
|