trace.ai-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/README.md +90 -0
- package/cli/traceAI.js +486 -0
- package/index.js +14 -642
- package/package.json +1 -1
- package/services/aiService.js +50 -0
- package/services/fileAnalyzer.js +60 -0
- package/services/folderAnalyzer.js +164 -0
- package/services/imageService.js +66 -0
- package/utils/encryption.js +29 -0
- package/utils/fileUtils.js +101 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Trace AI CLI
|
|
2
|
+
|
|
3
|
+
A powerful AI-powered command-line interface tool for analyzing files, folders, images, and answering questions.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **File Analysis**: Analyze code files with detailed insights
|
|
8
|
+
- **Folder Analysis**: Understand project structures and architectures
|
|
9
|
+
- **Image Text Extraction**: Extract text from images with optional question answering
|
|
10
|
+
- **Context Management**: Maintain conversation context for follow-up queries
|
|
11
|
+
- **Interactive CLI**: User-friendly command-line interface
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Make the CLI executable:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
chmod +x index.js
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Interactive Mode
|
|
28
|
+
|
|
29
|
+
Start the interactive CLI:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
./index.js
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Commands
|
|
36
|
+
|
|
37
|
+
- `/file "path/to/file.js" [question]` - Analyze a file with optional question
|
|
38
|
+
- `/folder "path/to/folder" [question]` - Analyze a folder structure with optional question
|
|
39
|
+
- `/image "path/to/image.png" [question]` - Extract text from an image with optional question
|
|
40
|
+
- `/context <text>` - Set text context for conversations
|
|
41
|
+
- `/context-file "path/to/file"` - Add file content to context
|
|
42
|
+
- `/view-context` - View all contexts
|
|
43
|
+
- `/clear [text|file "path"]` - Clear specific or all contexts
|
|
44
|
+
- `/exit` - Exit the application
|
|
45
|
+
|
|
46
|
+
### Command Line Arguments
|
|
47
|
+
|
|
48
|
+
You can also use the CLI with command line arguments:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Analyze a file
|
|
52
|
+
./index.js file path/to/file.js "What does this code do?"
|
|
53
|
+
|
|
54
|
+
# Analyze a folder
|
|
55
|
+
./index.js folder path/to/folder "Explain the architecture"
|
|
56
|
+
|
|
57
|
+
# Extract text from an image
|
|
58
|
+
./index.js image path/to/image.png "What is shown in this image?"
|
|
59
|
+
|
|
60
|
+
# Ask a question
|
|
61
|
+
./index.js ask "Explain quantum computing"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Project Structure
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
├── cli/
|
|
68
|
+
│ └── traceAI.js # CLI interface implementation
|
|
69
|
+
├── services/
|
|
70
|
+
│ ├── aiService.js # AI processing service
|
|
71
|
+
│ ├── fileAnalyzer.js # File analysis service
|
|
72
|
+
│ ├── folderAnalyzer.js # Folder analysis service
|
|
73
|
+
│ └── imageService.js # Image processing service
|
|
74
|
+
├── utils/
|
|
75
|
+
│ ├── encryption.js # Encryption utilities
|
|
76
|
+
│ └── fileUtils.js # File handling utilities
|
|
77
|
+
├── index.js # Main entry point
|
|
78
|
+
├── package.json # Project metadata
|
|
79
|
+
└── README.md # Documentation
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Dependencies
|
|
83
|
+
|
|
84
|
+
- `node-fetch`: For making HTTP requests
|
|
85
|
+
- `figlet`: For ASCII art generation
|
|
86
|
+
- `chalk`: For colorful terminal output
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
package/cli/traceAI.js
ADDED
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
const readline = require('readline');
|
|
2
|
+
const figlet = require('figlet');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs').promises;
|
|
6
|
+
const { analyzeFile } = require('../services/fileAnalyzer');
|
|
7
|
+
const { analyzeFolderStructure } = require('../services/folderAnalyzer');
|
|
8
|
+
const { extractTextFromImage } = require('../services/imageService');
|
|
9
|
+
const { processWithAI } = require('../services/aiService');
|
|
10
|
+
|
|
11
|
+
class TraceAI {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.rl = readline.createInterface({
|
|
14
|
+
input: process.stdin,
|
|
15
|
+
output: process.stdout,
|
|
16
|
+
prompt: ''
|
|
17
|
+
});
|
|
18
|
+
this.contexts = [];
|
|
19
|
+
this.sessionStartTime = new Date();
|
|
20
|
+
this.queryCount = 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Enhanced startup with animated loading
|
|
24
|
+
async start() {
|
|
25
|
+
// Clear screen for clean start
|
|
26
|
+
console.clear();
|
|
27
|
+
|
|
28
|
+
// Animated startup sequence
|
|
29
|
+
await this.showLoadingAnimation();
|
|
30
|
+
|
|
31
|
+
// Main header with enhanced ASCII art
|
|
32
|
+
await this.displayHeader();
|
|
33
|
+
|
|
34
|
+
// Show welcome message and commands
|
|
35
|
+
this.displayWelcomeMessage();
|
|
36
|
+
|
|
37
|
+
// Start the interactive session
|
|
38
|
+
this.promptUser();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async showLoadingAnimation() {
|
|
42
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
43
|
+
const messages = [
|
|
44
|
+
'Initializing Trace.AI...',
|
|
45
|
+
'Loading AI modules...',
|
|
46
|
+
'Preparing analysis engines...',
|
|
47
|
+
'Ready to trace!'
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
for (let i = 0; i < messages.length; i++) {
|
|
51
|
+
for (let j = 0; j < 10; j++) {
|
|
52
|
+
process.stdout.write(`\r${chalk.blueBright(frames[j % frames.length])} ${chalk.white(messages[i])}`);
|
|
53
|
+
await new Promise(resolve => setTimeout(resolve, 80));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
console.log(`\r${chalk.green('✓')} ${chalk.white('Trace.Ai initialized successfully!')}\n`);
|
|
57
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async displayHeader() {
|
|
61
|
+
// Create enhanced ASCII art
|
|
62
|
+
const asciiArt = figlet.textSync('TRACE.AI', {
|
|
63
|
+
font: 'ANSI Shadow',
|
|
64
|
+
horizontalLayout: 'fitted',
|
|
65
|
+
verticalLayout: 'default'
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Enhanced header with gradient effect
|
|
69
|
+
console.log(chalk.bold.blueBright(asciiArt));
|
|
70
|
+
|
|
71
|
+
// Subtitle and version info
|
|
72
|
+
console.log(chalk.gray.bold(' ') + chalk.white.bold('AI powered CLI Platform'));
|
|
73
|
+
console.log(chalk.gray(' ') + chalk.gray('v1.0.4 | Powered by Mixkey'));
|
|
74
|
+
|
|
75
|
+
// Dynamic separator
|
|
76
|
+
const width = process.stdout.columns || 80;
|
|
77
|
+
console.log(chalk.blueBright('═'.repeat(Math.min(width, 80))));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
displayWelcomeMessage() {
|
|
81
|
+
// Welcome section with better formatting
|
|
82
|
+
console.log(chalk.bold.green('\nWelcome to Trace.AI CLI'));
|
|
83
|
+
console.log();
|
|
84
|
+
// Enhanced command documentation
|
|
85
|
+
console.log(chalk.bold.cyan('📋 AVAILABLE COMMANDS'));
|
|
86
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
87
|
+
|
|
88
|
+
const commands = [
|
|
89
|
+
{
|
|
90
|
+
cmd: '/file <path> [question]',
|
|
91
|
+
desc: 'Analyze any code file with AI insights',
|
|
92
|
+
example: '/file "src/app.js" explain the main function',
|
|
93
|
+
icon: '📄'
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
cmd: '/folder <path> [question]',
|
|
97
|
+
desc: 'Analyze entire project structure',
|
|
98
|
+
example: '/folder "src/" what is the architecture?',
|
|
99
|
+
icon: '📁'
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
cmd: '/image <path> [question]',
|
|
103
|
+
desc: 'Analyze image content',
|
|
104
|
+
example: '/image "diagram.png" explain this flowchart',
|
|
105
|
+
icon: '🖼️'
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
cmd: '/context <text>',
|
|
109
|
+
desc: 'Add contextual information',
|
|
110
|
+
example: '/context This is a React project using TypeScript',
|
|
111
|
+
icon: '💭'
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
cmd: '/context-file <path>',
|
|
115
|
+
desc: 'Add file content as context',
|
|
116
|
+
example: '/context-file "README.md"',
|
|
117
|
+
icon: '📋'
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
cmd: '/view-context',
|
|
121
|
+
desc: 'Display all active contexts',
|
|
122
|
+
example: '/view-context',
|
|
123
|
+
icon: '👁️'
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
cmd: '/clear [type]',
|
|
127
|
+
desc: 'Clear contexts or screen',
|
|
128
|
+
example: '/clear or /clear context',
|
|
129
|
+
icon: '🧹'
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
cmd: '/help',
|
|
133
|
+
desc: 'Show detailed help information',
|
|
134
|
+
example: '/help',
|
|
135
|
+
icon: '❓'
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
cmd: '/stats',
|
|
139
|
+
desc: 'Show session statistics',
|
|
140
|
+
example: '/stats',
|
|
141
|
+
icon: '📊'
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
cmd: '/exit',
|
|
145
|
+
desc: 'Exit the application',
|
|
146
|
+
example: '/exit',
|
|
147
|
+
icon: '👋'
|
|
148
|
+
}
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
commands.forEach(({ cmd, desc, icon }) => {
|
|
152
|
+
console.log(`${chalk.blueBright(icon)} ${chalk.bold.magenta(cmd.padEnd(25))} ${chalk.gray(desc)}`);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
console.log(chalk.gray('\n' + '━'.repeat(50)));
|
|
156
|
+
// Quick start section
|
|
157
|
+
console.log(chalk.bold.cyan('⚡ QUICK START'));
|
|
158
|
+
console.log(chalk.gray('━'.repeat(20)));
|
|
159
|
+
console.log(chalk.white('• Type ') + chalk.cyan('/help') + chalk.white(' for detailed guidance'));
|
|
160
|
+
console.log(chalk.white('• Use ') + chalk.cyan('Tab') + chalk.white(' for auto-completion (when available)'));
|
|
161
|
+
console.log(chalk.white('• Start with ') + chalk.cyan('/file "your-file.js"') + chalk.white(' to analyze code'));
|
|
162
|
+
console.log(chalk.white('• Or just ask any question directly!'));
|
|
163
|
+
|
|
164
|
+
// Status bar
|
|
165
|
+
this.displayStatusBar();
|
|
166
|
+
|
|
167
|
+
console.log(chalk.gray('\n' + '─'.repeat(60)));
|
|
168
|
+
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
displayStatusBar() {
|
|
172
|
+
const uptime = Math.floor((new Date() - this.sessionStartTime) / 1000);
|
|
173
|
+
const contextCount = this.contexts.length;
|
|
174
|
+
|
|
175
|
+
console.log(chalk.gray('\n┌─ SESSION INFO ') + chalk.gray('─'.repeat(34)));
|
|
176
|
+
console.log(chalk.gray('│ ') + chalk.white('Uptime: ') + chalk.green(`${uptime}s`) +
|
|
177
|
+
chalk.gray(' │ ') + chalk.white('Contexts: ') + chalk.cyan(contextCount) +
|
|
178
|
+
chalk.gray(' │ ') + chalk.white('Queries: ') + chalk.blueBright(this.queryCount));
|
|
179
|
+
console.log(chalk.gray('└─') + chalk.gray('─'.repeat(48)));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
promptUser() {
|
|
183
|
+
// Enhanced prompt with status indicators
|
|
184
|
+
const contextIndicator = this.contexts.length > 0 ? chalk.cyan(`[${this.contexts.length}]`) : '';
|
|
185
|
+
const prompt = `${chalk.bold.blueBright('Trace.Ai')} ${contextIndicator}${chalk.gray('>')} `;
|
|
186
|
+
|
|
187
|
+
this.rl.question(prompt, async (input) => {
|
|
188
|
+
try {
|
|
189
|
+
if (input.trim()) {
|
|
190
|
+
this.queryCount++;
|
|
191
|
+
await this.handleInput(input);
|
|
192
|
+
}
|
|
193
|
+
} catch (error) {
|
|
194
|
+
this.displayError(error.message);
|
|
195
|
+
}
|
|
196
|
+
this.promptUser();
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async handleInput(input) {
|
|
201
|
+
const trimmedInput = input.trim();
|
|
202
|
+
|
|
203
|
+
if (!trimmedInput) return;
|
|
204
|
+
|
|
205
|
+
// Command routing with enhanced feedback
|
|
206
|
+
const commands = {
|
|
207
|
+
'/file': () => this.handleFileCommand(trimmedInput),
|
|
208
|
+
'/folder': () => this.handleFolderCommand(trimmedInput),
|
|
209
|
+
'/image': () => this.handleImageCommand(trimmedInput),
|
|
210
|
+
'/context ': () => this.handleContextCommand(trimmedInput),
|
|
211
|
+
'/context-file': () => this.handleContextFileCommand(trimmedInput),
|
|
212
|
+
'/view-context': () => this.displayContexts(),
|
|
213
|
+
'/clear': () => this.handleClearCommand(trimmedInput),
|
|
214
|
+
'/help': () => this.displayHelp(),
|
|
215
|
+
'/stats': () => this.displayStats(),
|
|
216
|
+
'/exit': () => this.close()
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Find and execute command
|
|
220
|
+
const commandKey = Object.keys(commands).find(cmd => trimmedInput.startsWith(cmd));
|
|
221
|
+
|
|
222
|
+
if (commandKey) {
|
|
223
|
+
await commands[commandKey]();
|
|
224
|
+
} else {
|
|
225
|
+
await this.handleTextQuery(trimmedInput);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async handleFileCommand(input) {
|
|
230
|
+
const parts = this.parseCommand(input);
|
|
231
|
+
if (!this.validateCommand(parts, 2, 'Usage: /file <file_path> [query]')) return;
|
|
232
|
+
|
|
233
|
+
const filePath = this.cleanPath(parts[1]);
|
|
234
|
+
const query = parts.slice(2).join(' ').replace(/^"|"$/g, '') || 'Analyze this file';
|
|
235
|
+
|
|
236
|
+
await this.executeWithSpinner(
|
|
237
|
+
`Analyzing file: ${path.basename(filePath)}`,
|
|
238
|
+
async () => {
|
|
239
|
+
const result = await analyzeFile(path.resolve(filePath), query);
|
|
240
|
+
this.displayResult('File Analysis', result.text, filePath);
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async handleFolderCommand(input) {
|
|
246
|
+
const parts = this.parseCommand(input);
|
|
247
|
+
if (!this.validateCommand(parts, 2, 'Usage: /folder <folder_path> [query]')) return;
|
|
248
|
+
|
|
249
|
+
const folderPath = this.cleanPath(parts[1]);
|
|
250
|
+
const query = parts.slice(2).join(' ').replace(/^"|"$/g, '') || 'Analyze this folder structure';
|
|
251
|
+
|
|
252
|
+
await this.executeWithSpinner(
|
|
253
|
+
`Analyzing folder: ${path.basename(folderPath)}`,
|
|
254
|
+
async () => {
|
|
255
|
+
const result = await analyzeFolderStructure(path.resolve(folderPath), query);
|
|
256
|
+
this.displayResult('Folder Analysis', result.text, folderPath);
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async handleImageCommand(input) {
|
|
262
|
+
const parts = this.parseCommand(input);
|
|
263
|
+
if (!this.validateCommand(parts, 2, 'Usage: /image <image_path> [query]')) return;
|
|
264
|
+
|
|
265
|
+
const imagePath = this.cleanPath(parts[1]);
|
|
266
|
+
const query = parts.slice(2).join(' ').replace(/^"|"$/g, '') || 'Describe this image';
|
|
267
|
+
|
|
268
|
+
await this.executeWithSpinner(
|
|
269
|
+
`Analyzing image: ${path.basename(imagePath)}`,
|
|
270
|
+
async () => {
|
|
271
|
+
const result = await extractTextFromImage(path.resolve(imagePath), query);
|
|
272
|
+
this.displayResult('Image Analysis', result, imagePath);
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
handleContextCommand(input) {
|
|
278
|
+
const context = input.substring('/context '.length).trim();
|
|
279
|
+
if (context) {
|
|
280
|
+
this.contexts.push({
|
|
281
|
+
type: 'text',
|
|
282
|
+
content: context,
|
|
283
|
+
timestamp: new Date().toLocaleTimeString()
|
|
284
|
+
});
|
|
285
|
+
console.log(chalk.green('✓ Context added successfully'));
|
|
286
|
+
} else {
|
|
287
|
+
console.log(chalk.cyan('⚠️ No context provided'));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async handleContextFileCommand(input) {
|
|
292
|
+
const filePath = input.substring('/context-file'.length).trim().replace(/^"|"$/g, '');
|
|
293
|
+
if (!filePath) {
|
|
294
|
+
console.log(chalk.cyan('⚠️ No file path provided'));
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
const resolvedPath = path.resolve(filePath);
|
|
300
|
+
const content = await fs.readFile(resolvedPath, 'utf8');
|
|
301
|
+
this.contexts.push({
|
|
302
|
+
type: 'file',
|
|
303
|
+
content: `File ${path.basename(resolvedPath)}:\n${content}`,
|
|
304
|
+
filename: path.basename(resolvedPath),
|
|
305
|
+
timestamp: new Date().toLocaleTimeString()
|
|
306
|
+
});
|
|
307
|
+
console.log(chalk.green(`✓ File ${path.basename(resolvedPath)} added to context`));
|
|
308
|
+
} catch (error) {
|
|
309
|
+
this.displayError(`Error reading file: ${error.message}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
displayContexts() {
|
|
314
|
+
if (this.contexts.length === 0) {
|
|
315
|
+
console.log(chalk.cyan('📭 No active contexts'));
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
console.log(chalk.bold.green('\n📋 ACTIVE CONTEXTS'));
|
|
320
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
321
|
+
|
|
322
|
+
this.contexts.forEach((ctx, index) => {
|
|
323
|
+
const icon = ctx.type === 'file' ? '📄' : '💭';
|
|
324
|
+
const preview = ctx.content.substring(0, 80).replace(/\n/g, ' ');
|
|
325
|
+
const truncated = ctx.content.length > 80 ? '...' : '';
|
|
326
|
+
|
|
327
|
+
console.log(`${chalk.blueBright(icon)} ${chalk.bold(`[${index + 1}]`)} ${chalk.gray(ctx.timestamp)}`);
|
|
328
|
+
console.log(` ${chalk.white(preview)}${chalk.gray(truncated)}`);
|
|
329
|
+
if (index < this.contexts.length - 1) console.log();
|
|
330
|
+
});
|
|
331
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
handleClearCommand(input) {
|
|
335
|
+
if (input === '/clear' || input === '/clear all') {
|
|
336
|
+
this.contexts = [];
|
|
337
|
+
console.log(chalk.green('✓ All contexts cleared'));
|
|
338
|
+
} else if (input === '/clear screen') {
|
|
339
|
+
console.clear();
|
|
340
|
+
this.displayHeader();
|
|
341
|
+
} else if (input === '/clear context') {
|
|
342
|
+
this.contexts = [];
|
|
343
|
+
console.log(chalk.green('✓ Context cleared'));
|
|
344
|
+
} else {
|
|
345
|
+
console.log(chalk.cyan('Usage: /clear [all|context|screen]'));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
displayHelp() {
|
|
350
|
+
|
|
351
|
+
console.log(chalk.bold.green('\n📖 DETAILED HELP GUIDE'));
|
|
352
|
+
console.log(chalk.gray('━'.repeat(60)));
|
|
353
|
+
|
|
354
|
+
console.log(chalk.bold.cyan('\n🎯 GETTING STARTED'));
|
|
355
|
+
console.log('Trace.AI is an intelligent CLI tool that helps you understand and analyze files,');
|
|
356
|
+
console.log('folder structures, and images using advanced AI capabilities.\n');
|
|
357
|
+
|
|
358
|
+
console.log(chalk.bold.cyan('💡 TIPS FOR BETTER RESULTS'));
|
|
359
|
+
console.log('• Be specific in your questions');
|
|
360
|
+
console.log('• Use context to provide background information');
|
|
361
|
+
console.log('• Combine multiple commands for comprehensive analysis');
|
|
362
|
+
console.log('• File paths with spaces should be quoted\n');
|
|
363
|
+
|
|
364
|
+
console.log(chalk.bold.cyan('🔧 TROUBLESHOOTING'));
|
|
365
|
+
console.log('• Ensure file paths are correct and accessible');
|
|
366
|
+
console.log('• Check file permissions for read access');
|
|
367
|
+
console.log('• Use /stats to monitor your session');
|
|
368
|
+
console.log('• Use /clear screen to refresh the interface\n');
|
|
369
|
+
|
|
370
|
+
console.log(chalk.gray('Press any key to continue...'));
|
|
371
|
+
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
displayStats() {
|
|
375
|
+
const uptime = Math.floor((new Date() - this.sessionStartTime) / 1000);
|
|
376
|
+
const minutes = Math.floor(uptime / 60);
|
|
377
|
+
const seconds = uptime % 60;
|
|
378
|
+
|
|
379
|
+
console.log(chalk.bold.green('\n📊 SESSION STATISTICS'));
|
|
380
|
+
console.log(chalk.gray('━'.repeat(40)));
|
|
381
|
+
console.log(`${chalk.blueBright('🕐')} Session Duration: ${chalk.white(`${minutes}m ${seconds}s`)}`);
|
|
382
|
+
console.log(`${chalk.blueBright('💬')} Total Queries: ${chalk.white(this.queryCount)}`);
|
|
383
|
+
console.log(`${chalk.blueBright('📋')} Active Contexts: ${chalk.white(this.contexts.length)}`);
|
|
384
|
+
console.log(`${chalk.blueBright('🖥️')} Terminal Width: ${chalk.white(process.stdout.columns || 'Unknown')}`);
|
|
385
|
+
console.log(`${chalk.blueBright('📅')} Started: ${chalk.white(this.sessionStartTime.toLocaleString())}`);
|
|
386
|
+
console.log(chalk.gray('━'.repeat(40)));
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async handleTextQuery(input) {
|
|
390
|
+
await this.executeWithSpinner(
|
|
391
|
+
'Processing your query',
|
|
392
|
+
async () => {
|
|
393
|
+
const context = this.contexts.map(ctx => ctx.content).join('\n\n');
|
|
394
|
+
const result = await processWithAI(input, context);
|
|
395
|
+
this.displayResult('Trace.Ai Response', result);
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Utility methods
|
|
401
|
+
parseCommand(input) {
|
|
402
|
+
return input.match(/(?:[^\s"]+|"[^"]*")+/g) || [];
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
cleanPath(path) {
|
|
406
|
+
// First remove quotes from beginning and end
|
|
407
|
+
let cleanedPath = path.replace(/^"|"$/g, '');
|
|
408
|
+
// Then handle escaped spaces and other escaped characters
|
|
409
|
+
cleanedPath = cleanedPath.replace(/\\([ \(\)\[\]\{\}\&\^\%\$\#\@\!\,\.\;\:\'\"])/g, '$1');
|
|
410
|
+
return cleanedPath;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
validateCommand(parts, minLength, usage) {
|
|
414
|
+
if (!parts || parts.length < minLength) {
|
|
415
|
+
console.log(chalk.cyan(`⚠️ ${usage}`));
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
return true;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
async executeWithSpinner(message, task) {
|
|
422
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
423
|
+
let frameIndex = 0;
|
|
424
|
+
|
|
425
|
+
const spinner = setInterval(() => {
|
|
426
|
+
process.stdout.write(`\r${chalk.blueBright(frames[frameIndex])} ${chalk.white(message)}`);
|
|
427
|
+
frameIndex = (frameIndex + 1) % frames.length;
|
|
428
|
+
}, 100);
|
|
429
|
+
|
|
430
|
+
try {
|
|
431
|
+
await task();
|
|
432
|
+
clearInterval(spinner);
|
|
433
|
+
process.stdout.write(`\r${chalk.green('✓')} ${chalk.white(message)} ${chalk.gray('- Complete!')}\n`);
|
|
434
|
+
} catch (error) {
|
|
435
|
+
clearInterval(spinner);
|
|
436
|
+
process.stdout.write(`\r${chalk.red('✗')} ${chalk.white(message)} ${chalk.gray('- Failed!')}\n`);
|
|
437
|
+
this.displayError(error.message);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
displayResult(title, content, filePath = null) {
|
|
442
|
+
console.log(chalk.bold.blueBright(`\n${title.toUpperCase()}`));
|
|
443
|
+
if (filePath) {
|
|
444
|
+
console.log(chalk.gray(`📍 Source: ${filePath}`));
|
|
445
|
+
}
|
|
446
|
+
console.log(chalk.blueBright('═'.repeat(60)));
|
|
447
|
+
console.log(chalk.white(content));
|
|
448
|
+
console.log(chalk.blueBright('═'.repeat(60)));
|
|
449
|
+
console.log();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
displayError(message) {
|
|
453
|
+
console.log(chalk.red(`\n❌ Error: ${message}\n`));
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
close() {
|
|
457
|
+
|
|
458
|
+
// Farewell message
|
|
459
|
+
const farewell = figlet.textSync('Goodbye!', {
|
|
460
|
+
font: 'Small',
|
|
461
|
+
horizontalLayout: 'fitted'
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
console.log(chalk.blueBright(farewell));
|
|
465
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
466
|
+
console.log(chalk.bold.green('Thank you for using Trace.AI!'));
|
|
467
|
+
|
|
468
|
+
// Session summary
|
|
469
|
+
const uptime = Math.floor((new Date() - this.sessionStartTime) / 1000);
|
|
470
|
+
const minutes = Math.floor(uptime / 60);
|
|
471
|
+
const seconds = uptime % 60;
|
|
472
|
+
|
|
473
|
+
console.log(chalk.gray(`Session Duration: ${minutes}m ${seconds}s`));
|
|
474
|
+
console.log(chalk.gray(`Total Queries: ${this.queryCount}`));
|
|
475
|
+
console.log(chalk.gray(`Contexts Used: ${this.contexts.length}`));
|
|
476
|
+
|
|
477
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
478
|
+
console.log(chalk.cyan('Visit us at: https://traceai.netlify.app'));
|
|
479
|
+
console.log(chalk.gray('Have a great day! 👋\n'));
|
|
480
|
+
|
|
481
|
+
this.rl.close();
|
|
482
|
+
process.exit(0);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
module.exports = TraceAI;
|