trace.ai-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.
Files changed (2) hide show
  1. package/index.js +740 -0
  2. package/package.json +39 -0
package/index.js ADDED
@@ -0,0 +1,740 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs').promises;
4
+ const path = require('path');
5
+ const readline = require('readline');
6
+ const fetch = require('node-fetch');
7
+
8
+ // Core encryption/decryption logic from background.js
9
+ const ENCRYPTION_KEY = 'AlzaSyCVKlzUxK';
10
+
11
+ function encodeUnicode(str) {
12
+ const utf8Bytes = new TextEncoder().encode(str);
13
+ const base64 = Buffer.from(utf8Bytes).toString('base64');
14
+ return base64;
15
+ }
16
+
17
+ function decodeUnicode(str) {
18
+ const bytes = Buffer.from(str, 'base64');
19
+ return new TextDecoder().decode(bytes);
20
+ }
21
+
22
+ function encryptData(data) {
23
+ const jsonStr = JSON.stringify(data);
24
+ const encoded = encodeUnicode(jsonStr);
25
+ return encoded.split('').reverse().join('');
26
+ }
27
+
28
+ function decryptData(encoded) {
29
+ const reversed = encoded.split('').reverse().join('');
30
+ const decoded = decodeUnicode(reversed);
31
+ return JSON.parse(decoded);
32
+ }
33
+
34
+ // File type detection
35
+ function getFileType(filePath) {
36
+ const ext = path.extname(filePath).toLowerCase();
37
+ const codeExtensions = {
38
+ '.js': 'JavaScript',
39
+ '.jsx': 'React/JavaScript',
40
+ '.ts': 'TypeScript',
41
+ '.tsx': 'React/TypeScript',
42
+ '.py': 'Python',
43
+ '.java': 'Java',
44
+ '.cpp': 'C++',
45
+ '.c': 'C',
46
+ '.cs': 'C#',
47
+ '.php': 'PHP',
48
+ '.rb': 'Ruby',
49
+ '.go': 'Go',
50
+ '.rs': 'Rust',
51
+ '.swift': 'Swift',
52
+ '.kt': 'Kotlin',
53
+ '.scala': 'Scala',
54
+ '.html': 'HTML',
55
+ '.css': 'CSS',
56
+ '.scss': 'SCSS',
57
+ '.sass': 'SASS',
58
+ '.less': 'LESS',
59
+ '.vue': 'Vue.js',
60
+ '.svelte': 'Svelte',
61
+ '.json': 'JSON',
62
+ '.xml': 'XML',
63
+ '.yaml': 'YAML',
64
+ '.yml': 'YAML',
65
+ '.toml': 'TOML',
66
+ '.ini': 'INI',
67
+ '.conf': 'Config',
68
+ '.md': 'Markdown',
69
+ '.txt': 'Text',
70
+ '.sql': 'SQL',
71
+ '.sh': 'Shell Script',
72
+ '.bash': 'Bash Script',
73
+ '.zsh': 'Zsh Script',
74
+ '.ps1': 'PowerShell',
75
+ '.bat': 'Batch Script',
76
+ '.dockerfile': 'Dockerfile',
77
+ '.gitignore': 'Git Ignore',
78
+ '.env': 'Environment Variables'
79
+ };
80
+
81
+ const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg'];
82
+
83
+ if (imageExtensions.includes(ext)) {
84
+ return 'image';
85
+ }
86
+
87
+ return codeExtensions[ext] || 'Unknown';
88
+ }
89
+
90
+ function getMimeType(filePath) {
91
+ const ext = path.extname(filePath).toLowerCase();
92
+ const mimeTypes = {
93
+ '.jpg': 'image/jpeg',
94
+ '.jpeg': 'image/jpeg',
95
+ '.png': 'image/png',
96
+ '.gif': 'image/gif',
97
+ '.webp': 'image/webp',
98
+ '.bmp': 'image/bmp',
99
+ '.svg': 'image/svg+xml'
100
+ };
101
+ return mimeTypes[ext] || 'image/jpeg';
102
+ }
103
+
104
+ // File reading and processing
105
+ async function readFileContent(filePath) {
106
+ try {
107
+ const stats = await fs.stat(filePath);
108
+ if (stats.isDirectory()) {
109
+ throw new Error('Path is a directory, not a file');
110
+ }
111
+
112
+ // Check file size (limit to 1MB for safety)
113
+ if (stats.size > 1024 * 1024) {
114
+ throw new Error('File too large. Maximum size is 1MB');
115
+ }
116
+
117
+ const content = await fs.readFile(filePath, 'utf8');
118
+ return content;
119
+ } catch (error) {
120
+ if (error.code === 'ENOENT') {
121
+ throw new Error(`File not found: ${filePath}`);
122
+ }
123
+ throw error;
124
+ }
125
+ }
126
+
127
+ function buildSimpleFileTree(folderPath, items, statsCache, depth = 0) {
128
+ let tree = '';
129
+ const indent = ' '.repeat(depth);
130
+
131
+ for (const item of items) {
132
+ const itemPath = path.join(folderPath, item);
133
+ const stats = statsCache.get(itemPath);
134
+ tree += `${indent}${item}${stats.isDirectory() ? '/' : ''}\n`;
135
+
136
+ if (stats.isDirectory()) {
137
+ try {
138
+ const subItems = fs.readdirSync(itemPath);
139
+ const subStatsCache = new Map();
140
+ for (const subItem of subItems) {
141
+ const subItemPath = path.join(itemPath, subItem);
142
+ subStatsCache.set(subItemPath, fs.statSync(subItemPath));
143
+ }
144
+ tree += buildSimpleFileTree(itemPath, subItems, subStatsCache, depth + 1);
145
+ } catch (error) {
146
+ tree += `${indent} (error accessing directory)\n`;
147
+ }
148
+ }
149
+ }
150
+
151
+ return tree;
152
+ }
153
+
154
+ async function analyzeFolder(folderPath, maxDepth = 2, currentDepth = 0) {
155
+ try {
156
+ const stats = await fs.stat(folderPath);
157
+ if (!stats.isDirectory()) {
158
+ throw new Error('Path is not a directory');
159
+ }
160
+
161
+ const analysis = {
162
+ path: folderPath,
163
+ files: [],
164
+ folders: [],
165
+ fileTree: '', // Store simple file tree
166
+ summary: {
167
+ totalFiles: 0,
168
+ totalFolders: 0,
169
+ fileTypes: {},
170
+ languages: {},
171
+ size: 0
172
+ }
173
+ };
174
+
175
+ const items = await fs.readdir(folderPath);
176
+ const statsCache = new Map();
177
+
178
+ // Cache stats for all items
179
+ for (const item of items) {
180
+ const itemPath = path.join(folderPath, item);
181
+ statsCache.set(itemPath, await fs.stat(itemPath));
182
+ }
183
+
184
+ // Build simple file tree
185
+ analysis.fileTree = buildSimpleFileTree(folderPath, items, statsCache);
186
+
187
+ for (const item of items) {
188
+ const itemPath = path.join(folderPath, item);
189
+ const itemStats = statsCache.get(itemPath);
190
+
191
+ if (itemStats.isDirectory()) {
192
+ analysis.folders.push(item);
193
+ analysis.summary.totalFolders++;
194
+
195
+ if (currentDepth < maxDepth) {
196
+ try {
197
+ const subAnalysis = await analyzeFolder(itemPath, maxDepth, currentDepth + 1);
198
+ analysis.summary.totalFiles += subAnalysis.summary.totalFiles;
199
+ analysis.summary.totalFolders += subAnalysis.summary.totalFolders;
200
+ analysis.summary.size += subAnalysis.summary.size;
201
+
202
+ Object.keys(subAnalysis.summary.fileTypes).forEach(type => {
203
+ analysis.summary.fileTypes[type] = (analysis.summary.fileTypes[type] || 0) + subAnalysis.summary.fileTypes[type];
204
+ });
205
+ Object.keys(subAnalysis.summary.languages).forEach(lang => {
206
+ analysis.summary.languages[lang] = (analysis.summary.languages[lang] || 0) + subAnalysis.summary.languages[lang];
207
+ });
208
+ } catch (error) {
209
+ console.warn(`Warning: Cannot access folder ${itemPath}`);
210
+ }
211
+ }
212
+ } else {
213
+ const fileType = getFileType(itemPath);
214
+ analysis.files.push({
215
+ name: item,
216
+ type: fileType,
217
+ size: itemStats.size,
218
+ modified: itemStats.mtime
219
+ });
220
+
221
+ analysis.summary.totalFiles++;
222
+ analysis.summary.size += itemStats.size;
223
+ analysis.summary.fileTypes[fileType] = (analysis.summary.fileTypes[fileType] || 0) + 1;
224
+
225
+ if (fileType !== 'image' && fileType !== 'Unknown') {
226
+ analysis.summary.languages[fileType] = (analysis.summary.languages[fileType] || 0) + 1;
227
+ }
228
+ }
229
+ }
230
+
231
+ return analysis;
232
+ } catch (error) {
233
+ if (error.code === 'ENOENT') {
234
+ throw new Error(`Folder not found: ${folderPath}`);
235
+ }
236
+ if (error.code === 'EACCES') {
237
+ throw new Error(`Access denied: ${folderPath}`);
238
+ }
239
+ throw error;
240
+ }
241
+ }
242
+
243
+ // Image processing functions
244
+ async function convertImageToBase64(imagePath) {
245
+ try {
246
+ const imageBuffer = await fs.readFile(imagePath);
247
+ const base64 = imageBuffer.toString('base64');
248
+ const mimeType = getMimeType(imagePath);
249
+ return { base64, mimeType };
250
+ } catch (error) {
251
+ throw new Error(`Failed to read image: ${error.message}`);
252
+ }
253
+ }
254
+
255
+ async function extractTextFromImage(imagePath, question = '') {
256
+ try {
257
+ console.log('Processing...');
258
+ const { base64, mimeType } = await convertImageToBase64(imagePath);
259
+ const visionModels = ['kimi', 'mvrk', 'gma3', 'qvl72', 'llama-vision'];
260
+
261
+ const modelRequests = visionModels.map(model =>
262
+ fetch('https://traceai.dukeindustries7.workers.dev/', {
263
+ method: 'POST',
264
+ headers: { 'Content-Type': 'application/json' },
265
+ body: encryptData({
266
+ a: model,
267
+ q: 'Extract and return only the text from this image. Format it naturally.',
268
+ r: [],
269
+ i: [{ inlineData: { data: base64, mimeType } }],
270
+ c: ''
271
+ })
272
+ })
273
+ .then(res => res.text())
274
+ .then(decryptData)
275
+ );
276
+
277
+ const responses = await Promise.all(modelRequests);
278
+ const responseTexts = responses.map(r => r.text);
279
+
280
+ const finalResponse = await fetch('https://traceai.dukeindustries7.workers.dev/', {
281
+ method: 'POST',
282
+ headers: { 'Content-Type': 'application/json' },
283
+ body: encryptData({
284
+ a: 'gfinal',
285
+ q: question ?
286
+ `First extract and combine the text from this image, then answer this question about the extracted text: ${question}` :
287
+ 'Combine these extracted texts from an image into a single, coherent, and naturally formatted text. Remove duplicates and ensure clarity.',
288
+ r: responseTexts,
289
+ i: [{ inlineData: { data: base64, mimeType } }],
290
+ c: ''
291
+ })
292
+ });
293
+
294
+ const encryptedResult = await finalResponse.text();
295
+ const decryptedResult = decryptData(encryptedResult);
296
+ return decryptedResult.text || 'No text extracted from image'
297
+ } catch (error) {
298
+ console.error('āŒ Error extracting text from image:', error);
299
+ throw error;
300
+ }
301
+ }
302
+
303
+ async function processWithAI(prompt, context = '') {
304
+ try {
305
+ console.log('Processing...');
306
+ const models = ['kimi', 'mvrk', 'gma3', 'dsv3', 'qw32b', 'ms24b', 'll70b', 'qw3', 'mp4', 'nlm3'];
307
+
308
+ const modelRequests = models.map(model =>
309
+ fetch('https://traceai.dukeindustries7.workers.dev/', {
310
+ method: 'POST',
311
+ headers: { 'Content-Type': 'application/json' },
312
+ body: encryptData({
313
+ a: model,
314
+ q: prompt,
315
+ r: [],
316
+ i: [],
317
+ c: context
318
+ })
319
+ })
320
+ .then(res => res.text())
321
+ .then(decryptData)
322
+ );
323
+
324
+ const responses = await Promise.all(modelRequests);
325
+ const responseTexts = responses.map(r => r.text);
326
+
327
+ const finalResponse = await fetch('https://traceai.dukeindustries7.workers.dev/', {
328
+ method: 'POST',
329
+ headers: { 'Content-Type': 'application/json' },
330
+ body: encryptData({
331
+ a: 'gfinal',
332
+ q: prompt,
333
+ r: responseTexts.filter(text => text && typeof text === 'string'),
334
+ i: [],
335
+ c: context
336
+ })
337
+ });
338
+
339
+ const encryptedResult = await finalResponse.text();
340
+ const decryptedResult = decryptData(encryptedResult);
341
+ return decryptedResult.text || 'No response generated';
342
+ } catch (error) {
343
+ console.error('āŒ Processing error:', error.message);
344
+ throw error;
345
+ }
346
+ }
347
+
348
+ // File and folder analysis functions
349
+ async function analyzeFile(filePath, query = '') {
350
+ try {
351
+ const fileType = getFileType(filePath);
352
+
353
+ if (fileType === 'image') {
354
+ return await extractTextFromImage(filePath);
355
+ }
356
+
357
+ const content = await readFileContent(filePath);
358
+ const fileName = path.basename(filePath);
359
+
360
+ let prompt;
361
+ if (query) {
362
+ prompt = `File: ${fileName} (${fileType})
363
+ Content:
364
+ \`\`\`
365
+ ${content}
366
+ \`\`\`
367
+
368
+ User Question: ${query}`;
369
+ } else {
370
+ if (fileType !== 'Unknown' && fileType !== 'Text' && fileType !== 'Markdown') {
371
+ prompt = `Analyze this ${fileType} code file (${fileName}):
372
+
373
+ \`\`\`
374
+ ${content}
375
+ \`\`\`
376
+
377
+ Please provide:
378
+ 1. Code overview and purpose
379
+ 2. Key functions/components
380
+ 3. Potential issues or improvements
381
+ 4. Code quality assessment
382
+ 5. Suggestions for optimization`;
383
+ } else {
384
+ prompt = `Analyze this file content (${fileName}):
385
+
386
+ \`\`\`
387
+ ${content}
388
+ \`\`\`
389
+
390
+ Please provide a summary and analysis of the content.`;
391
+ }
392
+ }
393
+
394
+ const result = await processWithAI(prompt);
395
+ return { text: result || 'No response generated' }; // Ensure consistent return format
396
+ } catch (error) {
397
+ throw error;
398
+ }
399
+ }
400
+
401
+ async function analyzeFolderStructure(folderPath, query = '') {
402
+ try {
403
+ const analysis = await analyzeFolder(folderPath);
404
+
405
+ const structureText = `
406
+ Folder: ${analysis.path}
407
+ Files: ${analysis.summary.totalFiles}
408
+ Folders: ${analysis.summary.totalFolders}
409
+ Total Size: ${(analysis.summary.size / 1024).toFixed(2)} KB
410
+
411
+ Files and Directories:
412
+ ${analysis.fileTree}
413
+
414
+ File Types:
415
+ ${Object.entries(analysis.summary.fileTypes).map(([type, count]) => `- ${type}: ${count}`).join('\n')}
416
+
417
+ Languages/Technologies:
418
+ ${Object.entries(analysis.summary.languages).map(([lang, count]) => `- ${lang}: ${count} files`).join('\n')}
419
+ `;
420
+
421
+ let prompt;
422
+ if (query) {
423
+ prompt = `Project Structure:
424
+ ${structureText}
425
+
426
+ User Question: ${query}`;
427
+ } else {
428
+ prompt = `Analyze this project structure:
429
+ ${structureText}
430
+
431
+ Provide a brief overview of the project based on its file structure.`;
432
+ }
433
+
434
+ const result = await processWithAI(prompt);
435
+ return { text: result || 'No response generated' }; // Ensure text property is always defined
436
+ } catch (error) {
437
+ throw error;
438
+ }
439
+ }
440
+ // CLI Interface
441
+ class TraceAI {
442
+ constructor() {
443
+ this.rl = readline.createInterface({
444
+ input: process.stdin,
445
+ output: process.stdout
446
+ });
447
+ this.contexts = {
448
+ text: '',
449
+ files: new Map()
450
+ };
451
+ }
452
+
453
+ async start() {
454
+ console.log('šŸš€ Welcome to Trace.Ai CLI - Enhanced File & Code Analysis!');
455
+ console.log('\nCommands:');
456
+ console.log(' /file "path" question - Analyze a file with optional question');
457
+ console.log(' /folder "path" question - Analyze a folder structure with optional question');
458
+ console.log(' /image "path" - Analyze a image');
459
+ console.log(' /context <text> - Set text context for conversations');
460
+ console.log(' /context-file "path" - Add file context');
461
+ console.log(' /view-context - View all contexts');
462
+ console.log(' /clear [text|file "path"] - Clear specific or all contexts');
463
+ console.log(' /exit - Exit the application');
464
+ console.log(' Or just type your question directly\n');
465
+
466
+ console.log('šŸ’” Examples:');
467
+ console.log(' /file app.js - General code analysis');
468
+ console.log(' /file app.js explain this code in simple terms');
469
+ console.log(' /file app.js find bugs and security issues');
470
+ console.log(' /folder ./project - Project structure overview');
471
+ console.log(' /folder ./src what is the main architecture pattern?\n');
472
+
473
+ this.promptUser();
474
+ }
475
+
476
+ promptUser() {
477
+ this.rl.question('Trace.Ai> ', async (input) => {
478
+ await this.handleInput(input.trim());
479
+ this.promptUser();
480
+ });
481
+ }
482
+
483
+ async handleInput(input) {
484
+ if (!input) return;
485
+
486
+ try {
487
+ if (input.startsWith('/file ')) {
488
+ await this.handleFileCommand(input.substring(6).trim());
489
+ } else if (input.startsWith('/folder ')) {
490
+ await this.handleFolderCommand(input.substring(8).trim());
491
+ } else if (input.startsWith('/image ')) {
492
+ const parts = input.substring(7).trim().match(/(?:"[^"]*"|[^\s"]+)+/g) || [];
493
+ const imagePath = parts[0]?.replace(/\\/g, '').replace(/^"|"$/g, '');
494
+ const question = parts.slice(1).join(' ').replace(/^"|"$/g, '');
495
+ await this.handleImageCommand(imagePath, question);
496
+ } else if (input.startsWith('/context ')) {
497
+ const context = input.substring(9).trim();
498
+ this.contexts.text = context;
499
+ console.log('āœ… Text context set successfully');
500
+ } else if (input.startsWith('/context-file ')) {
501
+ const filePath = input.substring(13).trim().replace(/\\/g, '').replace(/^"|"$/g, '');
502
+ try {
503
+ const fileContent = await fs.readFile(filePath, 'utf8');
504
+ this.contexts.files.set(filePath, fileContent);
505
+ console.log(`āœ… File context added: ${filePath}`);
506
+ } catch (error) {
507
+ console.error(`āŒ Error reading file: ${error.message}`);
508
+ }
509
+ } else if (input === '/view-context') {
510
+ console.log('\nCurrent Contexts:');
511
+ console.log('Text Context:', this.contexts.text || '(none)');
512
+ console.log('\nFile Contexts:');
513
+ if (this.contexts.files.size === 0) {
514
+ console.log('(none)');
515
+ } else {
516
+ for (const [path] of this.contexts.files) {
517
+ console.log(`- ${path}`);
518
+ }
519
+ }
520
+ } else if (input.startsWith('/clear')) {
521
+ const parts = input.match(/(?:"[^"]*"|[^\s"]+)+/g) || [];
522
+ if (parts.length === 1) {
523
+ this.contexts.text = '';
524
+ this.contexts.files.clear();
525
+ console.log('āœ… All contexts cleared');
526
+ } else if (parts[1] === 'text') {
527
+ this.contexts.text = '';
528
+ console.log('āœ… Text context cleared');
529
+ } else if (parts[1] === 'file' && parts[2]) {
530
+ const filePath = parts[2].replace(/\\/g, '').replace(/^"|"$/g, '');
531
+ if (this.contexts.files.delete(filePath)) {
532
+ console.log(`āœ… File context cleared: ${filePath}`);
533
+ } else {
534
+ console.log(`āŒ No such file context: ${filePath}`);
535
+ }
536
+ } else {
537
+ console.log('āŒ Invalid clear command. Use: /clear [text|file <path>]');
538
+ }
539
+ } else if (input === '/exit') {
540
+ console.log('šŸ‘‹ Goodbye!');
541
+ process.exit(0);
542
+ } else {
543
+ await this.handleTextQuery(input);
544
+ }
545
+ } catch (error) {
546
+ console.error('āŒ Error:', error.message);
547
+ }
548
+ }
549
+
550
+ async handleFileCommand(input) {
551
+ // Use regex to split input, preserving quoted strings
552
+ const parts = input.match(/(?:"[^"]*"|[^\s"]+)+/g) || [];
553
+ const filePath = parts[0]?.replace(/\\/g, '').replace(/^"|"$/g, '');
554
+ const query = parts.slice(1).join(' ').replace(/^"|"$/g, '');
555
+
556
+ if (!filePath) {
557
+ console.error('āŒ Error: No file path provided');
558
+ return;
559
+ }
560
+
561
+ try {
562
+ const result = await analyzeFile(filePath, query);
563
+ console.log('\nšŸ“„ File Analysis:');
564
+ console.log('=' .repeat(50));
565
+ console.log(result.text || result); // Handle both object and string responses
566
+ console.log('=' .repeat(50) + '\n');
567
+ } catch (error) {
568
+ console.error('āŒ Error analyzing file:', error.message);
569
+ }
570
+ }
571
+
572
+ async handleFolderCommand(input) {
573
+ const parts = input.split(/\s+(?=(?:[^"]*"[^"]*")*[^"]*$)/);
574
+ const folderPath = parts[0].replace(/\\/g, '').replace(/^"|"$/g, '');
575
+ const query = parts.slice(1).join(' ').replace(/^"|"$/g, '');
576
+
577
+ try {
578
+ const result = await analyzeFolderStructure(folderPath, query);
579
+ console.log('\nšŸ“ Folder Analysis:');
580
+ console.log('=' .repeat(50));
581
+ console.log(result.text);
582
+ console.log('=' .repeat(50) + '\n');
583
+ } catch (error) {
584
+ console.error('āŒ Error analyzing folder:', error.message);
585
+ }
586
+ }
587
+
588
+ async handleImageCommand(imagePath, question = '') {
589
+ try {
590
+ await fs.access(imagePath);
591
+ const result = await extractTextFromImage(imagePath, question);
592
+ console.log('\nšŸ–¼ļø Image Analysis:');
593
+ console.log('=' .repeat(50));
594
+ console.log(result);
595
+ console.log('=' .repeat(50) + '\n');
596
+ } catch (error) {
597
+ if (error.code === 'ENOENT') {
598
+ console.error('āŒ Image file not found:', imagePath);
599
+ } else {
600
+ console.error('āŒ Error processing image:', error.message);
601
+ }
602
+ }
603
+ }
604
+
605
+ async handleTextQuery(query) {
606
+ try {
607
+ let combinedContext = this.contexts.text;
608
+ if (this.contexts.files.size > 0) {
609
+ combinedContext += '\n\nFile Contexts:\n';
610
+ for (const [path, content] of this.contexts.files) {
611
+ combinedContext += `\nFile: ${path}\n${content}\n`;
612
+ }
613
+ }
614
+ const result = await processWithAI(query, combinedContext);
615
+ console.log('\nTrace.Ai Response:');
616
+ console.log('=' .repeat(50));
617
+ console.log(result);
618
+ console.log('=' .repeat(50) + '\n');
619
+ } catch (error) {
620
+ console.error('āŒ Error processing query:', error.message);
621
+ }
622
+ }
623
+
624
+ close() {
625
+ this.rl.close();
626
+ }
627
+ }
628
+
629
+ // Handle CLI arguments
630
+ async function handleCliArgs() {
631
+ const args = process.argv.slice(2);
632
+
633
+ if (args.length === 0) {
634
+ const traceAI = new TraceAI();
635
+ await traceAI.start();
636
+ return;
637
+ }
638
+
639
+ const command = args[0];
640
+
641
+ if (command === 'file' && args[1]) {
642
+ const filePath = args[1];
643
+ const query = args.slice(2).join(' ');
644
+
645
+ try {
646
+ console.log('šŸ“„ Analyzing file...');
647
+ const result = await analyzeFile(filePath, query);
648
+ console.log('\nšŸ“„ File Analysis:');
649
+ console.log('=' .repeat(50));
650
+ console.log(result);
651
+ console.log('=' .repeat(50));
652
+ } catch (error) {
653
+ console.error('āŒ Error:', error.message);
654
+ process.exit(1);
655
+ }
656
+ } else if (command === 'folder' && args[1]) {
657
+ const folderPath = args[1];
658
+ const query = args.slice(2).join(' ');
659
+
660
+ try {
661
+ console.log('šŸ“ Analyzing folder...');
662
+ const result = await analyzeFolderStructure(folderPath, query);
663
+ console.log('\nšŸ“ Folder Analysis:');
664
+ console.log('=' .repeat(50));
665
+ console.log(result);
666
+ console.log('=' .repeat(50));
667
+ } catch (error) {
668
+ console.error('āŒ Error:', error.message);
669
+ process.exit(1);
670
+ }
671
+ } else if (command === 'image' && args[1]) {
672
+ try {
673
+ const imagePath = args[1];
674
+ const question = args.slice(2).join(' ');
675
+ console.log('šŸ–¼ļø Analysing Image...');
676
+ const result = await extractTextFromImage(imagePath, question);
677
+ console.log('\nšŸ–¼ļø Image Analysis:');
678
+ console.log('=' .repeat(50));
679
+ console.log(result);
680
+ console.log('=' .repeat(50));
681
+ } catch (error) {
682
+ console.error('āŒ Error:', error.message);
683
+ process.exit(1);
684
+ }
685
+ } else if (command === 'ask') {
686
+ const query = args.slice(1).join(' ');
687
+ if (!query) {
688
+ console.error('āŒ Please provide a question after "ask"');
689
+ process.exit(1);
690
+ }
691
+
692
+ try {
693
+ console.log('Processing your question...');
694
+ const result = await processWithAI(query);
695
+ console.log('\nTrace.Ai Response:');
696
+ console.log('=' .repeat(50));
697
+ console.log(result);
698
+ console.log('=' .repeat(50));
699
+ } catch (error) {
700
+ console.error('āŒ Error:', error.message);
701
+ if (error.code === 'ENOENT') {
702
+ console.error('File not found. Please check the path and try again.');
703
+ }
704
+ process.exit(1);
705
+ }
706
+ } else {
707
+ console.log('Trace.Ai - AI powered CLI tool ');
708
+ console.log('\nUsage:');
709
+ console.log(' trace-ai - Start interactive mode');
710
+ console.log(' trace-ai file "path" question - Analyze a file');
711
+ console.log(' trace-ai folder "path" question - Analyze a folder');
712
+ console.log(' trace-ai image "path" - Analyze a image');
713
+ console.log(' trace-ai ask question - Ask a question');
714
+ console.log('\nExamples:');
715
+ console.log(' trace-ai file ./app.js');
716
+ console.log(' trace-ai file ./app.js explain this code"');
717
+ console.log(' trace-ai file ./app.js find security vulnerabilities');
718
+ console.log(' trace-ai folder ./project');
719
+ console.log(' trace-ai folder ./src what is the architecture?');
720
+ console.log(' trace-ai image screenshot.png');
721
+ console.log(' trace-ai ask Explain quantum computing');
722
+ }
723
+ }
724
+
725
+ // Error handling
726
+ process.on('unhandledRejection', (reason, promise) => {
727
+ console.error('āŒ Unhandled Rejection at:', promise, 'reason:', reason);
728
+ });
729
+
730
+ process.on('uncaughtException', (error) => {
731
+ console.error('āŒ Uncaught Exception:', error);
732
+ process.exit(1);
733
+ });
734
+
735
+ // Start the application
736
+ if (require.main === module) {
737
+ handleCliArgs().catch(console.error);
738
+ }
739
+
740
+ module.exports = { TraceAI, processWithAI, extractTextFromImage, analyzeFile, analyzeFolderStructure };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "trace.ai-cli",
3
+ "version": "1.0.0",
4
+ "description": "A powerful AI-powered CLI tool",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "trace-ai": "index.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node index.js",
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "ai",
15
+ "cli",
16
+ "code-analysis",
17
+ "file-analysis",
18
+ "code-review",
19
+ "bug-detection",
20
+ "text-processing",
21
+ "image-text-extraction",
22
+ "ocr",
23
+ "artificial-intelligence",
24
+ "command-line",
25
+ "tool",
26
+ "developer-tools",
27
+ "code-quality",
28
+ "project-analysis"
29
+ ],
30
+ "author": "Dukeindustries7",
31
+ "license": "MIT",
32
+ "dependencies": {
33
+ "node-fetch": "^2.6.7"
34
+ },
35
+ "engines": {
36
+ "node": ">=14.0.0"
37
+ },
38
+ "homepage": "https://github.com/yourusername/trace-ai-cli#readme"
39
+ }