trace.ai-cli 1.1.9 → 1.2.1

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.
@@ -1,60 +1,135 @@
1
- const path = require('path');
2
- const { getFileType, readFileContent } = require('../utils/fileUtils');
3
- const { processWithAI } = require('./aiService');
4
- const { extractTextFromImage } = require('./imageService');
5
-
6
- async function analyzeFile(filePath, query = '') {
7
- try {
8
- const fileType = getFileType(filePath);
9
-
10
- if (fileType === 'image') {
11
- return await extractTextFromImage(filePath);
12
- }
13
-
14
- const content = await readFileContent(filePath);
15
- const fileName = path.basename(filePath);
16
-
17
- let prompt;
18
- if (query) {
19
- prompt = `File: ${fileName} (${fileType})
20
- Content:
21
- \`\`\`
22
- ${content}
23
- \`\`\`
24
-
25
- User Question: ${query}`;
26
- } else {
27
- if (fileType !== 'Unknown' && fileType !== 'Text' && fileType !== 'Markdown') {
28
- prompt = `Analyze this ${fileType} code file (${fileName}):
29
-
30
- \`\`\`
31
- ${content}
32
- \`\`\`
33
-
34
- Please provide:
35
- 1. Code overview and purpose
36
- 2. Key functions/components
37
- 3. Potential issues or improvements
38
- 4. Code quality assessment
39
- 5. Suggestions for optimization`;
40
- } else {
41
- prompt = `Analyze this file content (${fileName}):
42
-
43
- \`\`\`
44
- ${content}
45
- \`\`\`
46
-
47
- Please provide a summary and analysis of the content.`;
48
- }
49
- }
50
-
51
- const result = await processWithAI(prompt);
52
- return { text: result || 'No response generated' }; // Ensure consistent return format
53
- } catch (error) {
54
- throw error;
55
- }
56
- }
57
-
58
- module.exports = {
59
- analyzeFile
60
- };
1
+ const path = require('path');
2
+ const fs = require('fs').promises;
3
+ const pdfParse = require('pdf-parse');
4
+ const { getFileType, readFileContent } = require('../utils/fileUtils');
5
+ const { processWithAI } = require('./aiService');
6
+ const { extractTextFromImage } = require('./imageService');
7
+
8
+ async function analyzeFile(filePath, query = '', mode = 2) {
9
+ try {
10
+ const fileType = getFileType(filePath);
11
+
12
+ // Handle images - use vision API only for images
13
+ if (fileType === 'image') {
14
+ const result = await extractTextFromImage(filePath, query, mode);
15
+ return { text: result };
16
+ }
17
+
18
+ // Handle documents (PDFs, Word, etc.)
19
+ if (fileType === 'document') {
20
+ const fileName = path.basename(filePath);
21
+ const ext = path.extname(filePath).toLowerCase();
22
+
23
+ // Extract text from PDF
24
+ if (ext === '.pdf') {
25
+ try {
26
+ const dataBuffer = await fs.readFile(filePath);
27
+ const pdfData = await pdfParse(dataBuffer);
28
+ const content = pdfData.text;
29
+
30
+ if (!content || content.trim().length === 0) {
31
+ return {
32
+ text: `❌ **Unable to Extract Text from PDF**\n\n` +
33
+ `The PDF "${fileName}" appears to be empty or contains only images/scanned content.\n\n` +
34
+ `**Try using the /image command for scanned PDFs:**\n` +
35
+ `\`/image "${filePath}" ${query || 'analyze this document'}\``
36
+ };
37
+ }
38
+
39
+ // Build prompt for AI analysis
40
+ let prompt;
41
+ if (query) {
42
+ prompt = `PDF Document: ${fileName}
43
+ Content:
44
+ \`\`\`
45
+ ${content}
46
+ \`\`\`
47
+
48
+ User Question: ${query}`;
49
+ } else {
50
+ prompt = `Analyze this PDF document (${fileName}):
51
+
52
+ \`\`\`
53
+ ${content}
54
+ \`\`\`
55
+
56
+ Please provide a comprehensive summary and analysis of the document.`;
57
+ }
58
+
59
+ const result = await processWithAI(prompt, '', mode);
60
+ return { text: result || 'No response generated' };
61
+
62
+ } catch (pdfError) {
63
+ return {
64
+ text: `❌ **Error Reading PDF**\n\n` +
65
+ `Failed to extract text from "${fileName}": ${pdfError.message}\n\n` +
66
+ `**Possible reasons:**\n` +
67
+ `- The PDF is corrupted or password-protected\n` +
68
+ `- The PDF contains only images (scanned document)\n\n` +
69
+ `**Try using /image command for scanned PDFs:**\n` +
70
+ `\`/image "${filePath}" ${query || 'analyze this document'}\``
71
+ };
72
+ }
73
+ }
74
+
75
+ // For other document types (Word, Excel, etc.)
76
+ return {
77
+ text: `❌ **Document Type Not Supported**\n\n` +
78
+ `The file "${fileName}" is a ${ext.toUpperCase()} document.\n\n` +
79
+ `**Supported formats:**\n` +
80
+ `- PDF files (.pdf) - Text extraction supported\n` +
81
+ `- Text files (.txt, .md, etc.)\n` +
82
+ `- Code files (.js, .py, .java, etc.)\n\n` +
83
+ `**For ${ext.toUpperCase()} files:**\n` +
84
+ `Please convert to PDF or text format first.`
85
+ };
86
+ }
87
+
88
+ // Handle text-based files
89
+ const content = await readFileContent(filePath);
90
+ const fileName = path.basename(filePath);
91
+
92
+ let prompt;
93
+ if (query) {
94
+ prompt = `File: ${fileName} (${fileType})
95
+ Content:
96
+ \`\`\`
97
+ ${content}
98
+ \`\`\`
99
+
100
+ User Question: ${query}`;
101
+ } else {
102
+ if (fileType !== 'Unknown' && fileType !== 'Text' && fileType !== 'Markdown') {
103
+ prompt = `Analyze this ${fileType} code file (${fileName}):
104
+
105
+ \`\`\`
106
+ ${content}
107
+ \`\`\`
108
+
109
+ Please provide:
110
+ 1. Code overview and purpose
111
+ 2. Key functions/components
112
+ 3. Potential issues or improvements
113
+ 4. Code quality assessment
114
+ 5. Suggestions for optimization`;
115
+ } else {
116
+ prompt = `Analyze this file content (${fileName}):
117
+
118
+ \`\`\`
119
+ ${content}
120
+ \`\`\`
121
+
122
+ Please provide a summary and analysis of the content.`;
123
+ }
124
+ }
125
+
126
+ const result = await processWithAI(prompt, '', mode);
127
+ return { text: result || 'No response generated' };
128
+ } catch (error) {
129
+ throw error;
130
+ }
131
+ }
132
+
133
+ module.exports = {
134
+ analyzeFile
135
+ };
@@ -1,101 +1,106 @@
1
- const fs = require('fs').promises;
2
- const path = require('path');
3
-
4
- // File type detection
5
- function getFileType(filePath) {
6
- const ext = path.extname(filePath).toLowerCase();
7
- const codeExtensions = {
8
- '.js': 'JavaScript',
9
- '.jsx': 'React/JavaScript',
10
- '.ts': 'TypeScript',
11
- '.tsx': 'React/TypeScript',
12
- '.py': 'Python',
13
- '.java': 'Java',
14
- '.cpp': 'C++',
15
- '.c': 'C',
16
- '.cs': 'C#',
17
- '.php': 'PHP',
18
- '.rb': 'Ruby',
19
- '.go': 'Go',
20
- '.rs': 'Rust',
21
- '.swift': 'Swift',
22
- '.kt': 'Kotlin',
23
- '.scala': 'Scala',
24
- '.html': 'HTML',
25
- '.css': 'CSS',
26
- '.scss': 'SCSS',
27
- '.sass': 'SASS',
28
- '.less': 'LESS',
29
- '.vue': 'Vue.js',
30
- '.svelte': 'Svelte',
31
- '.json': 'JSON',
32
- '.xml': 'XML',
33
- '.yaml': 'YAML',
34
- '.yml': 'YAML',
35
- '.toml': 'TOML',
36
- '.ini': 'INI',
37
- '.conf': 'Config',
38
- '.md': 'Markdown',
39
- '.txt': 'Text',
40
- '.sql': 'SQL',
41
- '.sh': 'Shell Script',
42
- '.bash': 'Bash Script',
43
- '.zsh': 'Zsh Script',
44
- '.ps1': 'PowerShell',
45
- '.bat': 'Batch Script',
46
- '.dockerfile': 'Dockerfile',
47
- '.gitignore': 'Git Ignore',
48
- '.env': 'Environment Variables'
49
- };
50
-
51
- const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg'];
52
-
53
- if (imageExtensions.includes(ext)) {
54
- return 'image';
55
- }
56
-
57
- return codeExtensions[ext] || 'Unknown';
58
- }
59
-
60
- function getMimeType(filePath) {
61
- const ext = path.extname(filePath).toLowerCase();
62
- const mimeTypes = {
63
- '.jpg': 'image/jpeg',
64
- '.jpeg': 'image/jpeg',
65
- '.png': 'image/png',
66
- '.gif': 'image/gif',
67
- '.webp': 'image/webp',
68
- '.bmp': 'image/bmp',
69
- '.svg': 'image/svg+xml'
70
- };
71
- return mimeTypes[ext] || 'image/jpeg';
72
- }
73
-
74
- // File reading and processing
75
- async function readFileContent(filePath) {
76
- try {
77
- const stats = await fs.stat(filePath);
78
- if (stats.isDirectory()) {
79
- throw new Error('Path is a directory, not a file');
80
- }
81
-
82
- // Check file size (limit to 1MB for safety)
83
- if (stats.size > 1024 * 1024) {
84
- throw new Error('File too large. Maximum size is 1MB');
85
- }
86
-
87
- const content = await fs.readFile(filePath, 'utf8');
88
- return content;
89
- } catch (error) {
90
- if (error.code === 'ENOENT') {
91
- throw new Error(`File not found: ${filePath}`);
92
- }
93
- throw error;
94
- }
95
- }
96
-
97
- module.exports = {
98
- getFileType,
99
- getMimeType,
100
- readFileContent
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+
4
+ // File type detection
5
+ function getFileType(filePath) {
6
+ const ext = path.extname(filePath).toLowerCase();
7
+ const codeExtensions = {
8
+ '.js': 'JavaScript',
9
+ '.jsx': 'React/JavaScript',
10
+ '.ts': 'TypeScript',
11
+ '.tsx': 'React/TypeScript',
12
+ '.py': 'Python',
13
+ '.java': 'Java',
14
+ '.cpp': 'C++',
15
+ '.c': 'C',
16
+ '.cs': 'C#',
17
+ '.php': 'PHP',
18
+ '.rb': 'Ruby',
19
+ '.go': 'Go',
20
+ '.rs': 'Rust',
21
+ '.swift': 'Swift',
22
+ '.kt': 'Kotlin',
23
+ '.scala': 'Scala',
24
+ '.html': 'HTML',
25
+ '.css': 'CSS',
26
+ '.scss': 'SCSS',
27
+ '.sass': 'SASS',
28
+ '.less': 'LESS',
29
+ '.vue': 'Vue.js',
30
+ '.svelte': 'Svelte',
31
+ '.json': 'JSON',
32
+ '.xml': 'XML',
33
+ '.yaml': 'YAML',
34
+ '.yml': 'YAML',
35
+ '.toml': 'TOML',
36
+ '.ini': 'INI',
37
+ '.conf': 'Config',
38
+ '.md': 'Markdown',
39
+ '.txt': 'Text',
40
+ '.sql': 'SQL',
41
+ '.sh': 'Shell Script',
42
+ '.bash': 'Bash Script',
43
+ '.zsh': 'Zsh Script',
44
+ '.ps1': 'PowerShell',
45
+ '.dockerfile': 'Dockerfile',
46
+ '.gitignore': 'Git Ignore',
47
+ '.env': 'Environment Variables'
48
+ };
49
+
50
+ const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp', '.svg'];
51
+ const documentExtensions = ['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx'];
52
+
53
+ if (imageExtensions.includes(ext)) {
54
+ return 'image';
55
+ }
56
+
57
+ if (documentExtensions.includes(ext)) {
58
+ return 'document';
59
+ }
60
+
61
+ return codeExtensions[ext] || 'Unknown';
62
+ }
63
+
64
+ function getMimeType(filePath) {
65
+ const ext = path.extname(filePath).toLowerCase();
66
+ const mimeTypes = {
67
+ '.jpg': 'image/jpeg',
68
+ '.jpeg': 'image/jpeg',
69
+ '.png': 'image/png',
70
+ '.gif': 'image/gif',
71
+ '.webp': 'image/webp',
72
+ '.bmp': 'image/bmp',
73
+ '.svg': 'image/svg+xml',
74
+ '.pdf': 'application/pdf'
75
+ };
76
+ return mimeTypes[ext] || 'image/jpeg';
77
+ }
78
+
79
+ // File reading and processing
80
+ async function readFileContent(filePath) {
81
+ try {
82
+ const stats = await fs.stat(filePath);
83
+ if (stats.isDirectory()) {
84
+ throw new Error('Path is a directory, not a file');
85
+ }
86
+
87
+ // Check file size (limit to 1MB for safety)
88
+ if (stats.size > 1024 * 1024) {
89
+ throw new Error('File too large. Maximum size is 1MB');
90
+ }
91
+
92
+ const content = await fs.readFile(filePath, 'utf8');
93
+ return content;
94
+ } catch (error) {
95
+ if (error.code === 'ENOENT') {
96
+ throw new Error(`File not found: ${filePath}`);
97
+ }
98
+ throw error;
99
+ }
100
+ }
101
+
102
+ module.exports = {
103
+ getFileType,
104
+ getMimeType,
105
+ readFileContent
101
106
  };