@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,535 @@
1
+ /**
2
+ * DirectoryAccessManager - Manage directory access permissions for agents
3
+ *
4
+ * Purpose:
5
+ * - Control agent access to directories and files
6
+ * - Distinguish between read-only and write-enabled directories
7
+ * - Validate paths against access permissions
8
+ * - Provide working directory management
9
+ * - Support both absolute and relative path resolution
10
+ */
11
+
12
+ import path from 'path';
13
+ import fs from 'fs/promises';
14
+ import os from 'os';
15
+
16
+ class DirectoryAccessManager {
17
+ constructor(config = {}, logger = null) {
18
+ this.logger = logger;
19
+ this.config = config;
20
+
21
+ // Default system restrictions
22
+ this.systemRestrictedPaths = [
23
+ // System directories
24
+ '/etc',
25
+ '/var',
26
+ '/usr',
27
+ '/bin',
28
+ '/sbin',
29
+ '/boot',
30
+ '/dev',
31
+ '/proc',
32
+ '/sys',
33
+ // Windows system directories
34
+ 'C:\\Windows',
35
+ 'C:\\Program Files',
36
+ 'C:\\Program Files (x86)',
37
+ // User sensitive directories
38
+ path.join(os.homedir(), '.ssh'),
39
+ path.join(os.homedir(), '.aws'),
40
+ path.join(os.homedir(), '.config'),
41
+ // Common package managers
42
+ 'node_modules/.bin',
43
+ '.git/objects',
44
+ '.git/hooks'
45
+ ];
46
+ }
47
+
48
+ /**
49
+ * Create directory access configuration for an agent
50
+ * @param {Object} options - Access configuration options
51
+ * @returns {Object} Directory access configuration
52
+ */
53
+ createDirectoryAccess(options = {}) {
54
+ const {
55
+ workingDirectory = process.cwd(),
56
+ readOnlyDirectories = [],
57
+ writeEnabledDirectories = [],
58
+ restrictToProject = true,
59
+ allowSystemAccess = false,
60
+ customRestrictions = []
61
+ } = options;
62
+
63
+ // Normalize all paths to absolute
64
+ const workingDir = path.resolve(workingDirectory);
65
+ const readOnlyDirs = readOnlyDirectories.map(dir => this.normalizePath(dir, workingDir));
66
+ const writeEnabledDirs = writeEnabledDirectories.map(dir => this.normalizePath(dir, workingDir));
67
+
68
+ // If restrict to project, ensure working directory is included
69
+ const finalReadOnlyDirs = restrictToProject
70
+ ? [...new Set([...readOnlyDirs, workingDir])]
71
+ : readOnlyDirs;
72
+
73
+ const finalWriteEnabledDirs = restrictToProject
74
+ ? writeEnabledDirs.filter(dir => this.isPathWithinDirectory(dir, workingDir))
75
+ : writeEnabledDirs;
76
+
77
+ return {
78
+ workingDirectory: workingDir,
79
+ readOnlyDirectories: finalReadOnlyDirs,
80
+ writeEnabledDirectories: finalWriteEnabledDirs,
81
+ restrictToProject,
82
+ allowSystemAccess,
83
+ customRestrictions: customRestrictions.map(restriction => path.resolve(restriction)),
84
+ createdAt: new Date().toISOString(),
85
+ version: '1.0'
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Validate if a path can be accessed for reading
91
+ * @param {string} targetPath - Path to validate
92
+ * @param {Object} accessConfig - Directory access configuration
93
+ * @returns {Object} Validation result
94
+ */
95
+ validateReadAccess(targetPath, accessConfig) {
96
+ try {
97
+ const resolvedPath = this.resolvePath(targetPath, accessConfig.workingDirectory);
98
+
99
+ // Check system restrictions first
100
+ if (!accessConfig.allowSystemAccess && this.isSystemRestrictedPath(resolvedPath)) {
101
+ return {
102
+ allowed: false,
103
+ reason: 'System path access denied',
104
+ path: resolvedPath,
105
+ category: 'system_restricted'
106
+ };
107
+ }
108
+
109
+ // Check custom restrictions
110
+ if (this.isCustomRestricted(resolvedPath, accessConfig.customRestrictions)) {
111
+ return {
112
+ allowed: false,
113
+ reason: 'Custom restriction applied',
114
+ path: resolvedPath,
115
+ category: 'custom_restricted'
116
+ };
117
+ }
118
+
119
+ // If restricting to project, ensure path is within allowed boundaries
120
+ if (accessConfig.restrictToProject) {
121
+ const isWithinProject = this.isPathWithinAnyDirectory(resolvedPath, [
122
+ ...accessConfig.readOnlyDirectories,
123
+ ...accessConfig.writeEnabledDirectories
124
+ ]);
125
+
126
+ if (!isWithinProject) {
127
+ return {
128
+ allowed: false,
129
+ reason: 'Path outside project scope',
130
+ path: resolvedPath,
131
+ category: 'project_restricted'
132
+ };
133
+ }
134
+ }
135
+
136
+ // Check if path is within any allowed directory
137
+ const isWithinAllowed = this.isPathWithinAnyDirectory(resolvedPath, [
138
+ ...accessConfig.readOnlyDirectories,
139
+ ...accessConfig.writeEnabledDirectories
140
+ ]);
141
+
142
+ if (!isWithinAllowed && accessConfig.readOnlyDirectories.length > 0) {
143
+ return {
144
+ allowed: false,
145
+ reason: 'Path not in allowed directories',
146
+ path: resolvedPath,
147
+ category: 'directory_restricted'
148
+ };
149
+ }
150
+
151
+ return {
152
+ allowed: true,
153
+ path: resolvedPath,
154
+ category: 'allowed'
155
+ };
156
+
157
+ } catch (error) {
158
+ return {
159
+ allowed: false,
160
+ reason: `Path validation error: ${error.message}`,
161
+ path: targetPath,
162
+ category: 'validation_error'
163
+ };
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Validate if a path can be accessed for writing
169
+ * @param {string} targetPath - Path to validate
170
+ * @param {Object} accessConfig - Directory access configuration
171
+ * @returns {Object} Validation result
172
+ */
173
+ validateWriteAccess(targetPath, accessConfig) {
174
+ // First check read access
175
+ const readResult = this.validateReadAccess(targetPath, accessConfig);
176
+ if (!readResult.allowed) {
177
+ return {
178
+ ...readResult,
179
+ writeAllowed: false
180
+ };
181
+ }
182
+
183
+ const resolvedPath = readResult.path;
184
+
185
+ // Check if path is within write-enabled directories
186
+ const isWithinWriteEnabled = this.isPathWithinAnyDirectory(
187
+ resolvedPath,
188
+ accessConfig.writeEnabledDirectories
189
+ );
190
+
191
+ if (!isWithinWriteEnabled) {
192
+ // Check if it's in read-only directories
193
+ const isWithinReadOnly = this.isPathWithinAnyDirectory(
194
+ resolvedPath,
195
+ accessConfig.readOnlyDirectories
196
+ );
197
+
198
+ if (isWithinReadOnly) {
199
+ return {
200
+ allowed: false,
201
+ writeAllowed: false,
202
+ reason: 'Path is in read-only directory',
203
+ path: resolvedPath,
204
+ category: 'read_only_restricted'
205
+ };
206
+ }
207
+
208
+ return {
209
+ allowed: false,
210
+ writeAllowed: false,
211
+ reason: 'Path not in write-enabled directories',
212
+ path: resolvedPath,
213
+ category: 'write_restricted'
214
+ };
215
+ }
216
+
217
+ return {
218
+ allowed: true,
219
+ writeAllowed: true,
220
+ path: resolvedPath,
221
+ category: 'write_allowed'
222
+ };
223
+ }
224
+
225
+ /**
226
+ * Get the effective working directory for an agent
227
+ * @param {Object} accessConfig - Directory access configuration
228
+ * @returns {string} Working directory path
229
+ */
230
+ getWorkingDirectory(accessConfig) {
231
+ return accessConfig.workingDirectory || process.cwd();
232
+ }
233
+
234
+ /**
235
+ * List accessible directories for an agent
236
+ * @param {Object} accessConfig - Directory access configuration
237
+ * @returns {Object} Directory listing with permissions
238
+ */
239
+ getAccessibleDirectories(accessConfig) {
240
+ return {
241
+ workingDirectory: accessConfig.workingDirectory,
242
+ readOnly: [...accessConfig.readOnlyDirectories],
243
+ writeEnabled: [...accessConfig.writeEnabledDirectories],
244
+ projectRestricted: accessConfig.restrictToProject,
245
+ systemAccessAllowed: accessConfig.allowSystemAccess,
246
+ totalDirectories: accessConfig.readOnlyDirectories.length + accessConfig.writeEnabledDirectories.length
247
+ };
248
+ }
249
+
250
+ /**
251
+ * Update directory access configuration
252
+ * @param {Object} currentConfig - Current access configuration
253
+ * @param {Object} updates - Updates to apply
254
+ * @returns {Object} Updated configuration
255
+ */
256
+ updateDirectoryAccess(currentConfig, updates) {
257
+ const updatedConfig = { ...currentConfig };
258
+
259
+ if (updates.workingDirectory) {
260
+ updatedConfig.workingDirectory = path.resolve(updates.workingDirectory);
261
+ }
262
+
263
+ if (updates.readOnlyDirectories !== undefined) {
264
+ updatedConfig.readOnlyDirectories = updates.readOnlyDirectories.map(dir =>
265
+ this.normalizePath(dir, updatedConfig.workingDirectory)
266
+ );
267
+ }
268
+
269
+ if (updates.writeEnabledDirectories !== undefined) {
270
+ updatedConfig.writeEnabledDirectories = updates.writeEnabledDirectories.map(dir =>
271
+ this.normalizePath(dir, updatedConfig.workingDirectory)
272
+ );
273
+ }
274
+
275
+ if (updates.restrictToProject !== undefined) {
276
+ updatedConfig.restrictToProject = updates.restrictToProject;
277
+ }
278
+
279
+ if (updates.allowSystemAccess !== undefined) {
280
+ updatedConfig.allowSystemAccess = updates.allowSystemAccess;
281
+ }
282
+
283
+ if (updates.customRestrictions !== undefined) {
284
+ updatedConfig.customRestrictions = updates.customRestrictions.map(restriction =>
285
+ path.resolve(restriction)
286
+ );
287
+ }
288
+
289
+ updatedConfig.version = currentConfig.version || '1.0';
290
+ updatedConfig.updatedAt = new Date().toISOString();
291
+
292
+ return updatedConfig;
293
+ }
294
+
295
+ /**
296
+ * Validate directory access configuration
297
+ * @param {Object} accessConfig - Configuration to validate
298
+ * @returns {Object} Validation result
299
+ */
300
+ validateAccessConfiguration(accessConfig) {
301
+ const errors = [];
302
+ const warnings = [];
303
+
304
+ // Validate working directory exists
305
+ if (!accessConfig.workingDirectory) {
306
+ errors.push('Working directory is required');
307
+ } else {
308
+ // Convert relative paths to absolute paths relative to process.cwd()
309
+ if (!path.isAbsolute(accessConfig.workingDirectory)) {
310
+ accessConfig.workingDirectory = path.resolve(process.cwd(), accessConfig.workingDirectory);
311
+ }
312
+ }
313
+
314
+ // Validate directory arrays
315
+ if (!Array.isArray(accessConfig.readOnlyDirectories)) {
316
+ errors.push('readOnlyDirectories must be an array');
317
+ } else {
318
+ // Convert relative paths to absolute paths
319
+ accessConfig.readOnlyDirectories = accessConfig.readOnlyDirectories.map(dir =>
320
+ path.isAbsolute(dir) ? dir : path.resolve(process.cwd(), dir)
321
+ );
322
+ }
323
+
324
+ if (!Array.isArray(accessConfig.writeEnabledDirectories)) {
325
+ errors.push('writeEnabledDirectories must be an array');
326
+ } else {
327
+ // Convert relative paths to absolute paths
328
+ accessConfig.writeEnabledDirectories = accessConfig.writeEnabledDirectories.map(dir =>
329
+ path.isAbsolute(dir) ? dir : path.resolve(process.cwd(), dir)
330
+ );
331
+ }
332
+
333
+ // Check for overlapping directories
334
+ if (accessConfig.readOnlyDirectories && accessConfig.writeEnabledDirectories) {
335
+ const overlapping = this.findOverlappingPaths(
336
+ accessConfig.readOnlyDirectories,
337
+ accessConfig.writeEnabledDirectories
338
+ );
339
+
340
+ if (overlapping.length > 0) {
341
+ warnings.push(`Overlapping directories found: ${overlapping.join(', ')}`);
342
+ }
343
+ }
344
+
345
+ // Check for system path access
346
+ if (accessConfig.allowSystemAccess) {
347
+ warnings.push('System path access is enabled - use with caution');
348
+ }
349
+
350
+ // Validate paths exist (async check would be needed in real implementation)
351
+ const allPaths = [
352
+ ...accessConfig.readOnlyDirectories,
353
+ ...accessConfig.writeEnabledDirectories
354
+ ];
355
+
356
+ for (const dirPath of allPaths) {
357
+ if (!path.isAbsolute(dirPath)) {
358
+ errors.push(`Directory path must be absolute: ${dirPath}`);
359
+ }
360
+ }
361
+
362
+ return {
363
+ valid: errors.length === 0,
364
+ errors,
365
+ warnings,
366
+ summary: {
367
+ readOnlyCount: accessConfig.readOnlyDirectories?.length || 0,
368
+ writeEnabledCount: accessConfig.writeEnabledDirectories?.length || 0,
369
+ restrictToProject: accessConfig.restrictToProject,
370
+ allowSystemAccess: accessConfig.allowSystemAccess
371
+ }
372
+ };
373
+ }
374
+
375
+ /**
376
+ * Create relative path from absolute path within accessible directories
377
+ * @param {string} absolutePath - Absolute path to convert
378
+ * @param {Object} accessConfig - Directory access configuration
379
+ * @returns {string} Relative path or original if not within accessible directories
380
+ */
381
+ createRelativePath(absolutePath, accessConfig) {
382
+ const allDirectories = [
383
+ ...accessConfig.readOnlyDirectories,
384
+ ...accessConfig.writeEnabledDirectories,
385
+ accessConfig.workingDirectory
386
+ ];
387
+
388
+ for (const dir of allDirectories) {
389
+ if (this.isPathWithinDirectory(absolutePath, dir)) {
390
+ return path.relative(dir, absolutePath);
391
+ }
392
+ }
393
+
394
+ return absolutePath;
395
+ }
396
+
397
+ /**
398
+ * Resolve path relative to working directory or as absolute
399
+ * @private
400
+ */
401
+ resolvePath(targetPath, workingDirectory) {
402
+ if (path.isAbsolute(targetPath)) {
403
+ return path.normalize(targetPath);
404
+ }
405
+ return path.resolve(workingDirectory, targetPath);
406
+ }
407
+
408
+ /**
409
+ * Normalize path to absolute, resolving relative to working directory
410
+ * @private
411
+ */
412
+ normalizePath(targetPath, workingDirectory) {
413
+ if (path.isAbsolute(targetPath)) {
414
+ return path.normalize(targetPath);
415
+ }
416
+ return path.resolve(workingDirectory, targetPath);
417
+ }
418
+
419
+ /**
420
+ * Check if path is within a directory
421
+ * @private
422
+ */
423
+ isPathWithinDirectory(targetPath, parentDirectory) {
424
+ const relative = path.relative(parentDirectory, targetPath);
425
+ return !relative.startsWith('..') && !path.isAbsolute(relative);
426
+ }
427
+
428
+ /**
429
+ * Check if path is within any of the provided directories
430
+ * @private
431
+ */
432
+ isPathWithinAnyDirectory(targetPath, directories) {
433
+ return directories.some(dir => this.isPathWithinDirectory(targetPath, dir));
434
+ }
435
+
436
+ /**
437
+ * Check if path is system restricted
438
+ * @private
439
+ */
440
+ isSystemRestrictedPath(targetPath) {
441
+ return this.systemRestrictedPaths.some(restrictedPath => {
442
+ return targetPath.startsWith(restrictedPath) || targetPath === restrictedPath;
443
+ });
444
+ }
445
+
446
+ /**
447
+ * Check if path is custom restricted
448
+ * @private
449
+ */
450
+ isCustomRestricted(targetPath, customRestrictions) {
451
+ if (!customRestrictions || customRestrictions.length === 0) {
452
+ return false;
453
+ }
454
+
455
+ return customRestrictions.some(restriction => {
456
+ return targetPath.startsWith(restriction) || targetPath === restriction;
457
+ });
458
+ }
459
+
460
+ /**
461
+ * Find overlapping paths between two arrays
462
+ * @private
463
+ */
464
+ findOverlappingPaths(paths1, paths2) {
465
+ const overlapping = [];
466
+
467
+ for (const path1 of paths1) {
468
+ for (const path2 of paths2) {
469
+ if (this.isPathWithinDirectory(path1, path2) || this.isPathWithinDirectory(path2, path1)) {
470
+ overlapping.push(`${path1} <-> ${path2}`);
471
+ }
472
+ }
473
+ }
474
+
475
+ return overlapping;
476
+ }
477
+
478
+ /**
479
+ * Get directory access summary for logging/debugging
480
+ * @param {Object} accessConfig - Directory access configuration
481
+ * @returns {Object} Summary object
482
+ */
483
+ getAccessSummary(accessConfig) {
484
+ return {
485
+ workingDirectory: accessConfig.workingDirectory,
486
+ readOnlyCount: accessConfig.readOnlyDirectories.length,
487
+ writeEnabledCount: accessConfig.writeEnabledDirectories.length,
488
+ projectRestricted: accessConfig.restrictToProject,
489
+ systemAccessAllowed: accessConfig.allowSystemAccess,
490
+ customRestrictionsCount: accessConfig.customRestrictions?.length || 0,
491
+ configVersion: accessConfig.version || 'unknown',
492
+ lastUpdated: accessConfig.updatedAt || accessConfig.createdAt
493
+ };
494
+ }
495
+
496
+ /**
497
+ * Create default directory access for project-based agents
498
+ * @param {string} projectDir - Project directory path
499
+ * @returns {Object} Default directory access configuration
500
+ */
501
+ static createProjectDefaults(projectDir) {
502
+ const resolvedProject = path.resolve(projectDir);
503
+
504
+ return {
505
+ workingDirectory: resolvedProject,
506
+ readOnlyDirectories: [resolvedProject],
507
+ writeEnabledDirectories: [resolvedProject],
508
+ restrictToProject: true,
509
+ allowSystemAccess: false,
510
+ customRestrictions: [],
511
+ createdAt: new Date().toISOString(),
512
+ version: '1.0'
513
+ };
514
+ }
515
+
516
+ /**
517
+ * Create permissive directory access (use with caution)
518
+ * @param {string} workingDir - Working directory
519
+ * @returns {Object} Permissive directory access configuration
520
+ */
521
+ static createPermissiveDefaults(workingDir = process.cwd()) {
522
+ return {
523
+ workingDirectory: path.resolve(workingDir),
524
+ readOnlyDirectories: [os.homedir()],
525
+ writeEnabledDirectories: [path.resolve(workingDir)],
526
+ restrictToProject: false,
527
+ allowSystemAccess: false,
528
+ customRestrictions: [],
529
+ createdAt: new Date().toISOString(),
530
+ version: '1.0'
531
+ };
532
+ }
533
+ }
534
+
535
+ export default DirectoryAccessManager;