@loxia-labs/loxia-autopilot-one 1.0.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.
Files changed (80) hide show
  1. package/LICENSE +267 -0
  2. package/README.md +509 -0
  3. package/bin/cli.js +117 -0
  4. package/package.json +94 -0
  5. package/scripts/install-scanners.js +236 -0
  6. package/src/analyzers/CSSAnalyzer.js +297 -0
  7. package/src/analyzers/ConfigValidator.js +690 -0
  8. package/src/analyzers/ESLintAnalyzer.js +320 -0
  9. package/src/analyzers/JavaScriptAnalyzer.js +261 -0
  10. package/src/analyzers/PrettierFormatter.js +247 -0
  11. package/src/analyzers/PythonAnalyzer.js +266 -0
  12. package/src/analyzers/SecurityAnalyzer.js +729 -0
  13. package/src/analyzers/TypeScriptAnalyzer.js +247 -0
  14. package/src/analyzers/codeCloneDetector/analyzer.js +344 -0
  15. package/src/analyzers/codeCloneDetector/detector.js +203 -0
  16. package/src/analyzers/codeCloneDetector/index.js +160 -0
  17. package/src/analyzers/codeCloneDetector/parser.js +199 -0
  18. package/src/analyzers/codeCloneDetector/reporter.js +148 -0
  19. package/src/analyzers/codeCloneDetector/scanner.js +59 -0
  20. package/src/core/agentPool.js +1474 -0
  21. package/src/core/agentScheduler.js +2147 -0
  22. package/src/core/contextManager.js +709 -0
  23. package/src/core/messageProcessor.js +732 -0
  24. package/src/core/orchestrator.js +548 -0
  25. package/src/core/stateManager.js +877 -0
  26. package/src/index.js +631 -0
  27. package/src/interfaces/cli.js +549 -0
  28. package/src/interfaces/webServer.js +2162 -0
  29. package/src/modules/fileExplorer/controller.js +280 -0
  30. package/src/modules/fileExplorer/index.js +37 -0
  31. package/src/modules/fileExplorer/middleware.js +92 -0
  32. package/src/modules/fileExplorer/routes.js +125 -0
  33. package/src/modules/fileExplorer/types.js +44 -0
  34. package/src/services/aiService.js +1232 -0
  35. package/src/services/apiKeyManager.js +164 -0
  36. package/src/services/benchmarkService.js +366 -0
  37. package/src/services/budgetService.js +539 -0
  38. package/src/services/contextInjectionService.js +247 -0
  39. package/src/services/conversationCompactionService.js +637 -0
  40. package/src/services/errorHandler.js +810 -0
  41. package/src/services/fileAttachmentService.js +544 -0
  42. package/src/services/modelRouterService.js +366 -0
  43. package/src/services/modelsService.js +322 -0
  44. package/src/services/qualityInspector.js +796 -0
  45. package/src/services/tokenCountingService.js +536 -0
  46. package/src/tools/agentCommunicationTool.js +1344 -0
  47. package/src/tools/agentDelayTool.js +485 -0
  48. package/src/tools/asyncToolManager.js +604 -0
  49. package/src/tools/baseTool.js +800 -0
  50. package/src/tools/browserTool.js +920 -0
  51. package/src/tools/cloneDetectionTool.js +621 -0
  52. package/src/tools/dependencyResolverTool.js +1215 -0
  53. package/src/tools/fileContentReplaceTool.js +875 -0
  54. package/src/tools/fileSystemTool.js +1107 -0
  55. package/src/tools/fileTreeTool.js +853 -0
  56. package/src/tools/imageTool.js +901 -0
  57. package/src/tools/importAnalyzerTool.js +1060 -0
  58. package/src/tools/jobDoneTool.js +248 -0
  59. package/src/tools/seekTool.js +956 -0
  60. package/src/tools/staticAnalysisTool.js +1778 -0
  61. package/src/tools/taskManagerTool.js +2873 -0
  62. package/src/tools/terminalTool.js +2304 -0
  63. package/src/tools/webTool.js +1430 -0
  64. package/src/types/agent.js +519 -0
  65. package/src/types/contextReference.js +972 -0
  66. package/src/types/conversation.js +730 -0
  67. package/src/types/toolCommand.js +747 -0
  68. package/src/utilities/attachmentValidator.js +292 -0
  69. package/src/utilities/configManager.js +582 -0
  70. package/src/utilities/constants.js +722 -0
  71. package/src/utilities/directoryAccessManager.js +535 -0
  72. package/src/utilities/fileProcessor.js +307 -0
  73. package/src/utilities/logger.js +436 -0
  74. package/src/utilities/tagParser.js +1246 -0
  75. package/src/utilities/toolConstants.js +317 -0
  76. package/web-ui/build/index.html +15 -0
  77. package/web-ui/build/logo.png +0 -0
  78. package/web-ui/build/logo2.png +0 -0
  79. package/web-ui/build/static/index-CjkkcnFA.js +344 -0
  80. package/web-ui/build/static/index-Dy2bYbOa.css +1 -0
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Context Injection Service
3
+ * Builds dynamic context sections from active file attachments
4
+ */
5
+
6
+ import FileAttachmentService from './fileAttachmentService.js';
7
+
8
+ class ContextInjectionService {
9
+ constructor(config = {}, logger = null) {
10
+ this.config = config;
11
+ this.logger = logger;
12
+ this.attachmentService = new FileAttachmentService(config, logger);
13
+ }
14
+
15
+ /**
16
+ * Initialize service
17
+ * @returns {Promise<void>}
18
+ */
19
+ async initialize() {
20
+ await this.attachmentService.initialize();
21
+ }
22
+
23
+ /**
24
+ * Build dynamic context for an agent
25
+ * @param {string} agentId - Agent ID
26
+ * @returns {Promise<string>} Dynamic context section
27
+ */
28
+ async buildDynamicContext(agentId) {
29
+ try {
30
+ const activeAttachments = await this.attachmentService.getActiveAttachments(agentId);
31
+
32
+ if (activeAttachments.length === 0) {
33
+ return ''; // No context to inject
34
+ }
35
+
36
+ // Separate content and reference mode attachments
37
+ const contentFiles = activeAttachments.filter(a => a.mode === 'content');
38
+ const referenceFiles = activeAttachments.filter(a => a.mode === 'reference');
39
+
40
+ let contextSection = '';
41
+
42
+ // Build content files section
43
+ if (contentFiles.length > 0) {
44
+ contextSection += '\n<attached-files>\n';
45
+
46
+ for (const attachment of contentFiles) {
47
+ const content = await this.attachmentService.getAttachmentContent(attachment.fileId);
48
+ if (content) {
49
+ const formattedContent = this.formatContentFile(attachment, content);
50
+ contextSection += formattedContent + '\n';
51
+ }
52
+ }
53
+
54
+ contextSection += '</attached-files>\n';
55
+ }
56
+
57
+ // Build reference files section
58
+ if (referenceFiles.length > 0) {
59
+ contextSection += '\n<file-references>\n';
60
+
61
+ for (const attachment of referenceFiles) {
62
+ const formattedRef = this.formatReferenceFile(attachment);
63
+ contextSection += formattedRef + '\n';
64
+ }
65
+
66
+ contextSection += '</file-references>\n';
67
+ contextSection += '\nNote: Referenced files can be accessed using the filesystem tool if needed.\n';
68
+ }
69
+
70
+ return contextSection;
71
+ } catch (error) {
72
+ this.logger?.error('Error building dynamic context', { agentId, error: error.message });
73
+ return ''; // Return empty on error to avoid breaking the conversation
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Format content mode file
79
+ * @param {Object} attachment - Attachment metadata
80
+ * @param {string} content - File content
81
+ * @returns {string} Formatted XML
82
+ */
83
+ formatContentFile(attachment, content) {
84
+ const { fileName, fileType, size, contentType } = attachment;
85
+ const sizeKB = (size / 1024).toFixed(2);
86
+
87
+ // Format based on content type
88
+ if (contentType === 'text') {
89
+ return this.formatTextFile(attachment, content);
90
+ } else if (contentType === 'image') {
91
+ return this.formatImageFile(attachment, content);
92
+ } else if (contentType === 'pdf') {
93
+ return this.formatPdfFile(attachment, content);
94
+ }
95
+
96
+ // Fallback
97
+ return ` <file name="${this.escapeXml(fileName)}" type="${fileType}" size="${sizeKB}KB" mode="content">\n${this.escapeXml(content)}\n </file>`;
98
+ }
99
+
100
+ /**
101
+ * Format text file
102
+ * @param {Object} attachment - Attachment metadata
103
+ * @param {string} content - File content
104
+ * @returns {string} Formatted XML
105
+ */
106
+ formatTextFile(attachment, content) {
107
+ const { fileName, fileType, size } = attachment;
108
+ const sizeKB = (size / 1024).toFixed(2);
109
+
110
+ return ` <file name="${this.escapeXml(fileName)}" type="${fileType}" size="${sizeKB}KB" mode="content">\n${this.escapeXml(content)}\n </file>`;
111
+ }
112
+
113
+ /**
114
+ * Format image file
115
+ * @param {Object} attachment - Attachment metadata
116
+ * @param {string} base64Content - Base64 data URI
117
+ * @returns {string} Formatted XML
118
+ */
119
+ formatImageFile(attachment, base64Content) {
120
+ const { fileName, fileType, size } = attachment;
121
+ const sizeKB = (size / 1024).toFixed(2);
122
+
123
+ return ` <file name="${this.escapeXml(fileName)}" type="${fileType}" size="${sizeKB}KB" mode="content">\n${base64Content}\n </file>`;
124
+ }
125
+
126
+ /**
127
+ * Format PDF file
128
+ * @param {Object} attachment - Attachment metadata
129
+ * @param {string} extractedText - Extracted text from PDF
130
+ * @returns {string} Formatted XML
131
+ */
132
+ formatPdfFile(attachment, extractedText) {
133
+ const { fileName, fileType, size } = attachment;
134
+ const sizeKB = (size / 1024).toFixed(2);
135
+
136
+ return ` <file name="${this.escapeXml(fileName)}" type="${fileType}" size="${sizeKB}KB" mode="content">\n${this.escapeXml(extractedText)}\n </file>`;
137
+ }
138
+
139
+ /**
140
+ * Format reference mode file
141
+ * @param {Object} attachment - Attachment metadata
142
+ * @returns {string} Formatted XML
143
+ */
144
+ formatReferenceFile(attachment) {
145
+ const { fileName, originalPath, size, fileType, lastModified } = attachment;
146
+ const sizeFormatted = this.formatBytes(size);
147
+ const modifiedDate = new Date(lastModified).toISOString().split('T')[0];
148
+
149
+ return ` <file name="${this.escapeXml(fileName)}" path="${this.escapeXml(originalPath)}" size="${sizeFormatted}" type="${fileType}" modified="${modifiedDate}" />`;
150
+ }
151
+
152
+ /**
153
+ * Escape XML special characters
154
+ * @param {string} text - Text to escape
155
+ * @returns {string} Escaped text
156
+ */
157
+ escapeXml(text) {
158
+ if (!text) return '';
159
+ return text
160
+ .replace(/&/g, '&amp;')
161
+ .replace(/</g, '&lt;')
162
+ .replace(/>/g, '&gt;')
163
+ .replace(/"/g, '&quot;')
164
+ .replace(/'/g, '&apos;');
165
+ }
166
+
167
+ /**
168
+ * Format bytes to human-readable string
169
+ * @param {number} bytes
170
+ * @returns {string}
171
+ */
172
+ formatBytes(bytes) {
173
+ if (bytes === 0) return '0 Bytes';
174
+ const k = 1024;
175
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
176
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
177
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + sizes[i];
178
+ }
179
+
180
+ /**
181
+ * Estimate total tokens for active attachments
182
+ * @param {string} agentId - Agent ID
183
+ * @returns {Promise<number>} Total estimated tokens
184
+ */
185
+ async estimateTotalTokens(agentId) {
186
+ try {
187
+ const activeAttachments = await this.attachmentService.getActiveAttachments(agentId);
188
+ let total = 0;
189
+
190
+ for (const attachment of activeAttachments) {
191
+ if (attachment.mode === 'content') {
192
+ total += attachment.tokenEstimate || 0;
193
+ } else {
194
+ // Reference mode: estimate XML tag overhead
195
+ total += 20; // Approximate tokens for XML tag
196
+ }
197
+ }
198
+
199
+ return total;
200
+ } catch (error) {
201
+ this.logger?.error('Error estimating total tokens', { agentId, error: error.message });
202
+ return 0;
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Get summary of active attachments
208
+ * @param {string} agentId - Agent ID
209
+ * @returns {Promise<Object>} Summary object
210
+ */
211
+ async getAttachmentSummary(agentId) {
212
+ try {
213
+ const activeAttachments = await this.attachmentService.getActiveAttachments(agentId);
214
+
215
+ const summary = {
216
+ totalActive: activeAttachments.length,
217
+ contentMode: activeAttachments.filter(a => a.mode === 'content').length,
218
+ referenceMode: activeAttachments.filter(a => a.mode === 'reference').length,
219
+ estimatedTokens: 0,
220
+ files: []
221
+ };
222
+
223
+ for (const attachment of activeAttachments) {
224
+ summary.estimatedTokens += attachment.tokenEstimate || 0;
225
+ summary.files.push({
226
+ fileName: attachment.fileName,
227
+ mode: attachment.mode,
228
+ size: this.formatBytes(attachment.size),
229
+ tokens: attachment.tokenEstimate || 0
230
+ });
231
+ }
232
+
233
+ return summary;
234
+ } catch (error) {
235
+ this.logger?.error('Error getting attachment summary', { agentId, error: error.message });
236
+ return {
237
+ totalActive: 0,
238
+ contentMode: 0,
239
+ referenceMode: 0,
240
+ estimatedTokens: 0,
241
+ files: []
242
+ };
243
+ }
244
+ }
245
+ }
246
+
247
+ export default ContextInjectionService;