@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.
- package/LICENSE +267 -0
- package/README.md +509 -0
- package/bin/cli.js +117 -0
- package/package.json +94 -0
- package/scripts/install-scanners.js +236 -0
- package/src/analyzers/CSSAnalyzer.js +297 -0
- package/src/analyzers/ConfigValidator.js +690 -0
- package/src/analyzers/ESLintAnalyzer.js +320 -0
- package/src/analyzers/JavaScriptAnalyzer.js +261 -0
- package/src/analyzers/PrettierFormatter.js +247 -0
- package/src/analyzers/PythonAnalyzer.js +266 -0
- package/src/analyzers/SecurityAnalyzer.js +729 -0
- package/src/analyzers/TypeScriptAnalyzer.js +247 -0
- package/src/analyzers/codeCloneDetector/analyzer.js +344 -0
- package/src/analyzers/codeCloneDetector/detector.js +203 -0
- package/src/analyzers/codeCloneDetector/index.js +160 -0
- package/src/analyzers/codeCloneDetector/parser.js +199 -0
- package/src/analyzers/codeCloneDetector/reporter.js +148 -0
- package/src/analyzers/codeCloneDetector/scanner.js +59 -0
- package/src/core/agentPool.js +1474 -0
- package/src/core/agentScheduler.js +2147 -0
- package/src/core/contextManager.js +709 -0
- package/src/core/messageProcessor.js +732 -0
- package/src/core/orchestrator.js +548 -0
- package/src/core/stateManager.js +877 -0
- package/src/index.js +631 -0
- package/src/interfaces/cli.js +549 -0
- package/src/interfaces/webServer.js +2162 -0
- package/src/modules/fileExplorer/controller.js +280 -0
- package/src/modules/fileExplorer/index.js +37 -0
- package/src/modules/fileExplorer/middleware.js +92 -0
- package/src/modules/fileExplorer/routes.js +125 -0
- package/src/modules/fileExplorer/types.js +44 -0
- package/src/services/aiService.js +1232 -0
- package/src/services/apiKeyManager.js +164 -0
- package/src/services/benchmarkService.js +366 -0
- package/src/services/budgetService.js +539 -0
- package/src/services/contextInjectionService.js +247 -0
- package/src/services/conversationCompactionService.js +637 -0
- package/src/services/errorHandler.js +810 -0
- package/src/services/fileAttachmentService.js +544 -0
- package/src/services/modelRouterService.js +366 -0
- package/src/services/modelsService.js +322 -0
- package/src/services/qualityInspector.js +796 -0
- package/src/services/tokenCountingService.js +536 -0
- package/src/tools/agentCommunicationTool.js +1344 -0
- package/src/tools/agentDelayTool.js +485 -0
- package/src/tools/asyncToolManager.js +604 -0
- package/src/tools/baseTool.js +800 -0
- package/src/tools/browserTool.js +920 -0
- package/src/tools/cloneDetectionTool.js +621 -0
- package/src/tools/dependencyResolverTool.js +1215 -0
- package/src/tools/fileContentReplaceTool.js +875 -0
- package/src/tools/fileSystemTool.js +1107 -0
- package/src/tools/fileTreeTool.js +853 -0
- package/src/tools/imageTool.js +901 -0
- package/src/tools/importAnalyzerTool.js +1060 -0
- package/src/tools/jobDoneTool.js +248 -0
- package/src/tools/seekTool.js +956 -0
- package/src/tools/staticAnalysisTool.js +1778 -0
- package/src/tools/taskManagerTool.js +2873 -0
- package/src/tools/terminalTool.js +2304 -0
- package/src/tools/webTool.js +1430 -0
- package/src/types/agent.js +519 -0
- package/src/types/contextReference.js +972 -0
- package/src/types/conversation.js +730 -0
- package/src/types/toolCommand.js +747 -0
- package/src/utilities/attachmentValidator.js +292 -0
- package/src/utilities/configManager.js +582 -0
- package/src/utilities/constants.js +722 -0
- package/src/utilities/directoryAccessManager.js +535 -0
- package/src/utilities/fileProcessor.js +307 -0
- package/src/utilities/logger.js +436 -0
- package/src/utilities/tagParser.js +1246 -0
- package/src/utilities/toolConstants.js +317 -0
- package/web-ui/build/index.html +15 -0
- package/web-ui/build/logo.png +0 -0
- package/web-ui/build/logo2.png +0 -0
- package/web-ui/build/static/index-CjkkcnFA.js +344 -0
- 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, '&')
|
|
161
|
+
.replace(/</g, '<')
|
|
162
|
+
.replace(/>/g, '>')
|
|
163
|
+
.replace(/"/g, '"')
|
|
164
|
+
.replace(/'/g, ''');
|
|
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;
|