@loxia-labs/loxia-autopilot-one 1.0.1 → 1.0.3

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 (120) hide show
  1. package/README.md +44 -54
  2. package/bin/cli.js +1 -115
  3. package/bin/loxia-terminal-v2.js +3 -0
  4. package/bin/loxia-terminal.js +3 -0
  5. package/bin/start-with-terminal.js +3 -0
  6. package/package.json +14 -15
  7. package/scripts/install-scanners.js +1 -235
  8. package/src/analyzers/CSSAnalyzer.js +1 -297
  9. package/src/analyzers/ConfigValidator.js +1 -690
  10. package/src/analyzers/ESLintAnalyzer.js +1 -320
  11. package/src/analyzers/JavaScriptAnalyzer.js +1 -261
  12. package/src/analyzers/PrettierFormatter.js +1 -247
  13. package/src/analyzers/PythonAnalyzer.js +1 -266
  14. package/src/analyzers/SecurityAnalyzer.js +1 -729
  15. package/src/analyzers/TypeScriptAnalyzer.js +1 -247
  16. package/src/analyzers/codeCloneDetector/analyzer.js +1 -344
  17. package/src/analyzers/codeCloneDetector/detector.js +1 -203
  18. package/src/analyzers/codeCloneDetector/index.js +1 -160
  19. package/src/analyzers/codeCloneDetector/parser.js +1 -199
  20. package/src/analyzers/codeCloneDetector/reporter.js +1 -148
  21. package/src/analyzers/codeCloneDetector/scanner.js +1 -59
  22. package/src/core/agentPool.js +1 -1474
  23. package/src/core/agentScheduler.js +1 -2147
  24. package/src/core/contextManager.js +1 -709
  25. package/src/core/messageProcessor.js +1 -732
  26. package/src/core/orchestrator.js +1 -548
  27. package/src/core/stateManager.js +1 -877
  28. package/src/index.js +1 -631
  29. package/src/interfaces/cli.js +1 -549
  30. package/src/interfaces/terminal/__tests__/smoke/advancedFeatures.test.js +1 -0
  31. package/src/interfaces/terminal/__tests__/smoke/agentControl.test.js +1 -0
  32. package/src/interfaces/terminal/__tests__/smoke/agents.test.js +1 -0
  33. package/src/interfaces/terminal/__tests__/smoke/components.test.js +1 -0
  34. package/src/interfaces/terminal/__tests__/smoke/connection.test.js +1 -0
  35. package/src/interfaces/terminal/__tests__/smoke/enhancements.test.js +1 -0
  36. package/src/interfaces/terminal/__tests__/smoke/imports.test.js +1 -0
  37. package/src/interfaces/terminal/__tests__/smoke/messages.test.js +1 -0
  38. package/src/interfaces/terminal/__tests__/smoke/tools.test.js +1 -0
  39. package/src/interfaces/terminal/api/apiClient.js +1 -0
  40. package/src/interfaces/terminal/api/messageRouter.js +1 -0
  41. package/src/interfaces/terminal/api/session.js +1 -0
  42. package/src/interfaces/terminal/api/websocket.js +1 -0
  43. package/src/interfaces/terminal/components/AgentCreator.js +1 -0
  44. package/src/interfaces/terminal/components/AgentEditor.js +1 -0
  45. package/src/interfaces/terminal/components/AgentSwitcher.js +1 -0
  46. package/src/interfaces/terminal/components/ErrorBoundary.js +1 -0
  47. package/src/interfaces/terminal/components/ErrorPanel.js +1 -0
  48. package/src/interfaces/terminal/components/Header.js +1 -0
  49. package/src/interfaces/terminal/components/HelpPanel.js +1 -0
  50. package/src/interfaces/terminal/components/InputBox.js +1 -0
  51. package/src/interfaces/terminal/components/Layout.js +1 -0
  52. package/src/interfaces/terminal/components/LoadingSpinner.js +1 -0
  53. package/src/interfaces/terminal/components/MessageList.js +1 -0
  54. package/src/interfaces/terminal/components/MultilineTextInput.js +1 -0
  55. package/src/interfaces/terminal/components/SearchPanel.js +1 -0
  56. package/src/interfaces/terminal/components/SettingsPanel.js +1 -0
  57. package/src/interfaces/terminal/components/StatusBar.js +1 -0
  58. package/src/interfaces/terminal/components/TextInput.js +1 -0
  59. package/src/interfaces/terminal/config/agentEditorConstants.js +1 -0
  60. package/src/interfaces/terminal/config/constants.js +1 -0
  61. package/src/interfaces/terminal/index.js +1 -0
  62. package/src/interfaces/terminal/state/useAgentControl.js +1 -0
  63. package/src/interfaces/terminal/state/useAgents.js +1 -0
  64. package/src/interfaces/terminal/state/useConnection.js +1 -0
  65. package/src/interfaces/terminal/state/useMessages.js +1 -0
  66. package/src/interfaces/terminal/state/useTools.js +1 -0
  67. package/src/interfaces/terminal/utils/debugLogger.js +1 -0
  68. package/src/interfaces/terminal/utils/settingsStorage.js +1 -0
  69. package/src/interfaces/terminal/utils/theme.js +1 -0
  70. package/src/interfaces/webServer.js +1 -2162
  71. package/src/modules/fileExplorer/controller.js +1 -280
  72. package/src/modules/fileExplorer/index.js +1 -37
  73. package/src/modules/fileExplorer/middleware.js +1 -92
  74. package/src/modules/fileExplorer/routes.js +1 -125
  75. package/src/modules/fileExplorer/types.js +1 -44
  76. package/src/services/aiService.js +1 -1232
  77. package/src/services/apiKeyManager.js +1 -164
  78. package/src/services/benchmarkService.js +1 -366
  79. package/src/services/budgetService.js +1 -539
  80. package/src/services/contextInjectionService.js +1 -247
  81. package/src/services/conversationCompactionService.js +1 -637
  82. package/src/services/errorHandler.js +1 -810
  83. package/src/services/fileAttachmentService.js +1 -544
  84. package/src/services/modelRouterService.js +1 -366
  85. package/src/services/modelsService.js +1 -322
  86. package/src/services/qualityInspector.js +1 -796
  87. package/src/services/tokenCountingService.js +1 -536
  88. package/src/tools/agentCommunicationTool.js +1 -1344
  89. package/src/tools/agentDelayTool.js +1 -485
  90. package/src/tools/asyncToolManager.js +1 -604
  91. package/src/tools/baseTool.js +1 -800
  92. package/src/tools/browserTool.js +1 -920
  93. package/src/tools/cloneDetectionTool.js +1 -621
  94. package/src/tools/dependencyResolverTool.js +1 -1215
  95. package/src/tools/fileContentReplaceTool.js +1 -875
  96. package/src/tools/fileSystemTool.js +1 -1107
  97. package/src/tools/fileTreeTool.js +1 -853
  98. package/src/tools/imageTool.js +1 -901
  99. package/src/tools/importAnalyzerTool.js +1 -1060
  100. package/src/tools/jobDoneTool.js +1 -248
  101. package/src/tools/seekTool.js +1 -956
  102. package/src/tools/staticAnalysisTool.js +1 -1778
  103. package/src/tools/taskManagerTool.js +1 -2873
  104. package/src/tools/terminalTool.js +1 -2304
  105. package/src/tools/webTool.js +1 -1430
  106. package/src/types/agent.js +1 -519
  107. package/src/types/contextReference.js +1 -972
  108. package/src/types/conversation.js +1 -730
  109. package/src/types/toolCommand.js +1 -747
  110. package/src/utilities/attachmentValidator.js +1 -292
  111. package/src/utilities/configManager.js +1 -582
  112. package/src/utilities/constants.js +1 -722
  113. package/src/utilities/directoryAccessManager.js +1 -535
  114. package/src/utilities/fileProcessor.js +1 -307
  115. package/src/utilities/logger.js +1 -436
  116. package/src/utilities/tagParser.js +1 -1246
  117. package/src/utilities/toolConstants.js +1 -317
  118. package/web-ui/build/index.html +2 -2
  119. package/web-ui/build/static/{index-Dy2bYbOa.css → index-CClD1090.css} +1 -1
  120. package/web-ui/build/static/{index-CjkkcnFA.js → index-lCBai6dX.js} +66 -67
@@ -1,1778 +1 @@
1
- /**
2
- * StaticAnalysisTool - Static code analysis for finding errors without execution
3
- *
4
- * Purpose:
5
- * - Analyze code files for syntax, type, and import errors
6
- * - Detect programming languages and frameworks
7
- * - Provide actionable error references with line numbers
8
- * - Support single file, multiple files, and project-wide analysis
9
- * - Use official language parsers for accurate results
10
- */
11
-
12
- import { BaseTool } from './baseTool.js';
13
- import TagParser from '../utilities/tagParser.js';
14
- import DirectoryAccessManager from '../utilities/directoryAccessManager.js';
15
- import fs from 'fs/promises';
16
- import path from 'path';
17
- import crypto from 'crypto';
18
-
19
- import {
20
- STATIC_ANALYSIS,
21
- TOOL_STATUS,
22
- SYSTEM_DEFAULTS
23
- } from '../utilities/constants.js';
24
-
25
- class StaticAnalysisTool extends BaseTool {
26
- constructor(config = {}, logger = null) {
27
- super(config, logger);
28
-
29
- // Tool metadata
30
- this.requiresProject = true;
31
- this.isAsync = false;
32
- this.timeout = config.timeout || STATIC_ANALYSIS.ANALYSIS_TIMEOUT;
33
- this.maxConcurrentOperations = config.maxConcurrentOperations || 1;
34
-
35
- // Analysis settings
36
- this.maxFileSize = config.maxFileSize || STATIC_ANALYSIS.MAX_FILE_SIZE_FOR_ANALYSIS;
37
- this.maxFilesPerBatch = config.maxFilesPerBatch || STATIC_ANALYSIS.MAX_FILES_PER_BATCH;
38
- this.enableCache = config.enableCache !== false && STATIC_ANALYSIS.ENABLE_CACHE;
39
-
40
- // Cache for analysis results
41
- this.analysisCache = new Map();
42
- this.cacheExpiry = STATIC_ANALYSIS.CACHE_DURATION;
43
-
44
- // Performance optimization settings
45
- this.parallelAnalysis = config.parallelAnalysis !== false;
46
- this.maxParallelFiles = config.maxParallelFiles || 10;
47
- this.useContentHash = config.useContentHash !== false;
48
-
49
- // Performance metrics
50
- this.metrics = {
51
- totalAnalyses: 0,
52
- cacheHits: 0,
53
- cacheMisses: 0,
54
- totalAnalysisTime: 0,
55
- filesAnalyzed: 0,
56
- parallelBatches: 0
57
- };
58
-
59
- // Directory access manager
60
- this.directoryAccessManager = new DirectoryAccessManager(config, logger);
61
-
62
- // Analyzers will be initialized lazily when needed
63
- this.analyzers = {
64
- javascript: null,
65
- typescript: null,
66
- python: null,
67
- css: null,
68
- scss: null,
69
- less: null,
70
- eslint: null,
71
- security: null,
72
- config: null
73
- };
74
-
75
- // Formatters will be initialized lazily when needed
76
- this.formatters = {
77
- prettier: null
78
- };
79
- }
80
-
81
- /**
82
- * Get tool description for LLM consumption
83
- * @returns {string} Tool description
84
- */
85
- getDescription() {
86
- return `
87
- Static Code Analysis Tool: Analyze code files for errors without execution
88
-
89
- This tool performs static analysis on code files to find syntax errors, type errors, import issues, and other problems without running the code. It uses official language parsers for accurate results.
90
-
91
- SUPPORTED LANGUAGES:
92
- - JavaScript (.js, .jsx, .mjs, .cjs)
93
- - TypeScript (.ts, .tsx)
94
- - Python (.py)
95
- - CSS (.css)
96
- - SCSS (.scss, .sass)
97
- - LESS (.less)
98
-
99
- USAGE - XML FORMAT:
100
-
101
- Single File Analysis:
102
- [tool id="staticanalysis"]
103
- <analyze file-path="src/index.js" />
104
- [/tool]
105
-
106
- Multiple Files Analysis:
107
- [tool id="staticanalysis"]
108
- <analyze file-path="src/index.js" />
109
- <analyze file-path="src/utils.js" />
110
- <analyze file-path="src/components/Button.jsx" />
111
- [/tool]
112
-
113
- Project-Wide Analysis:
114
- [tool id="staticanalysis"]
115
- <analyze-project directory="src" pattern="**/*.js" />
116
- [/tool]
117
-
118
- Auto-Fix Code Issues:
119
- [tool id="staticanalysis"]
120
- <fix file-path="src/app.js" />
121
- [/tool]
122
-
123
- Format Code:
124
- [tool id="staticanalysis"]
125
- <format file-path="src/app.js" />
126
- [/tool]
127
-
128
- USAGE - JSON FORMAT:
129
-
130
- \`\`\`json
131
- {
132
- "toolId": "staticanalysis",
133
- "actions": [
134
- {
135
- "type": "analyze",
136
- "filePath": "src/index.js"
137
- },
138
- {
139
- "type": "analyze-project",
140
- "directory": "src",
141
- "pattern": "**/*.{js,ts,py}"
142
- }
143
- ]
144
- }
145
- \`\`\`
146
-
147
- PARAMETERS:
148
- - file-path: Path to file to analyze (for single file)
149
- - directory: Directory to analyze (for project-wide)
150
- - pattern: Glob pattern for files to include (optional, defaults to language-specific patterns)
151
- - include-warnings: Include warnings in results (true/false, default: true)
152
- - max-errors: Maximum number of errors to return (default: all)
153
-
154
- OUTPUT FORMAT:
155
- Returns structured error information:
156
- - file: File path
157
- - line: Line number
158
- - column: Column number
159
- - severity: critical | error | warning | info
160
- - rule: Rule identifier
161
- - message: Human-readable description
162
- - category: syntax | type | import | style | security | performance | best_practice
163
- - fixable: Whether error can be auto-fixed
164
- - suggestion: Fix suggestion (if applicable)
165
- - remediation: Security remediation advice (for security issues)
166
-
167
- DETECTION:
168
- - Language: Automatically detected from file extension
169
- - Framework: Detected from package.json, requirements.txt, etc.
170
- - Context: Project structure analyzed for better accuracy
171
-
172
- EXAMPLES:
173
-
174
- Find all errors in a JavaScript file:
175
- [tool id="staticanalysis"]
176
- <analyze file-path="src/app.js" />
177
- [/tool]
178
-
179
- Analyze TypeScript with type checking:
180
- [tool id="staticanalysis"]
181
- <analyze file-path="src/types.ts" />
182
- [/tool]
183
-
184
- Check all Python files in a directory:
185
- [tool id="staticanalysis"]
186
- <analyze-project directory="backend" pattern="**/*.py" />
187
- [/tool]
188
-
189
- LIMITATIONS:
190
- - File size limit: ${Math.round(this.maxFileSize / 1024 / 1024)}MB per file
191
- - Batch limit: ${this.maxFilesPerBatch} files per operation
192
- - Analysis timeout: ${this.timeout / 1000} seconds
193
- - Only supports languages with built-in analyzers
194
- `;
195
- }
196
-
197
- /**
198
- * Parse parameters from tool command content
199
- * @param {string} content - Raw tool command content
200
- * @returns {Object} Parsed parameters
201
- */
202
- parseParameters(content) {
203
- try {
204
- const params = {};
205
- const actions = [];
206
-
207
- this.logger?.debug('StaticAnalysis tool parsing parameters', {
208
- contentLength: content.length,
209
- contentPreview: content.substring(0, 200)
210
- });
211
-
212
- // Extract self-closing <analyze> tags
213
- // Pattern: <analyze ...attributes... />
214
- // We need to capture everything between 'analyze' and '/>' which includes file paths with /
215
- const analyzePattern = /<analyze\s+(.+?)\/>/g;
216
- let match;
217
-
218
- while ((match = analyzePattern.exec(content)) !== null) {
219
- const attributeString = match[1].trim();
220
- const parser = new TagParser();
221
- const attributes = parser.parseAttributes(attributeString);
222
-
223
- const action = {
224
- type: 'analyze',
225
- ...attributes
226
- };
227
-
228
- // Normalize attribute names
229
- if (action['file-path']) {
230
- action.filePath = action['file-path'];
231
- delete action['file-path'];
232
- }
233
- if (action['include-warnings']) {
234
- action.includeWarnings = action['include-warnings'] === 'true';
235
- delete action['include-warnings'];
236
- }
237
- if (action['max-errors']) {
238
- action.maxErrors = parseInt(action['max-errors'], 10);
239
- delete action['max-errors'];
240
- }
241
-
242
- actions.push(action);
243
- }
244
-
245
- // Extract self-closing <analyze-project> tags
246
- const projectPattern = /<analyze-project\s+(.+?)\/>/g;
247
-
248
- while ((match = projectPattern.exec(content)) !== null) {
249
- const attributeString = match[1].trim();
250
- const parser = new TagParser();
251
- const attributes = parser.parseAttributes(attributeString);
252
-
253
- const action = {
254
- type: 'analyze-project',
255
- ...attributes
256
- };
257
-
258
- // Normalize attribute names
259
- if (action['include-warnings']) {
260
- action.includeWarnings = action['include-warnings'] === 'true';
261
- delete action['include-warnings'];
262
- }
263
- if (action['max-errors']) {
264
- action.maxErrors = parseInt(action['max-errors'], 10);
265
- delete action['max-errors'];
266
- }
267
-
268
- actions.push(action);
269
- }
270
-
271
- // Extract self-closing <fix> tags
272
- const fixPattern = /<fix\s+(.+?)\/>/g;
273
-
274
- while ((match = fixPattern.exec(content)) !== null) {
275
- const attributeString = match[1].trim();
276
- const parser = new TagParser();
277
- const attributes = parser.parseAttributes(attributeString);
278
-
279
- const action = {
280
- type: 'fix',
281
- ...attributes
282
- };
283
-
284
- // Normalize attribute names
285
- if (action['file-path']) {
286
- action.filePath = action['file-path'];
287
- delete action['file-path'];
288
- }
289
- if (action['write-file']) {
290
- action.writeFile = action['write-file'] === 'true';
291
- delete action['write-file'];
292
- }
293
-
294
- actions.push(action);
295
- }
296
-
297
- // Extract self-closing <format> tags
298
- const formatPattern = /<format\s+(.+?)\/>/g;
299
-
300
- while ((match = formatPattern.exec(content)) !== null) {
301
- const attributeString = match[1].trim();
302
- const parser = new TagParser();
303
- const attributes = parser.parseAttributes(attributeString);
304
-
305
- const action = {
306
- type: 'format',
307
- ...attributes
308
- };
309
-
310
- // Normalize attribute names
311
- if (action['file-path']) {
312
- action.filePath = action['file-path'];
313
- delete action['file-path'];
314
- }
315
- if (action['write-file']) {
316
- action.writeFile = action['write-file'] === 'true';
317
- delete action['write-file'];
318
- }
319
-
320
- actions.push(action);
321
- }
322
-
323
- // Extract self-closing <security-scan> tags
324
- const securityScanPattern = /<security-scan\s+(.+?)\/>/g;
325
-
326
- while ((match = securityScanPattern.exec(content)) !== null) {
327
- const attributeString = match[1].trim();
328
- const parser = new TagParser();
329
- const attributes = parser.parseAttributes(attributeString);
330
-
331
- const action = {
332
- type: 'security-scan',
333
- ...attributes
334
- };
335
-
336
- // Normalize attribute names
337
- if (action['file-path']) {
338
- action.filePath = action['file-path'];
339
- delete action['file-path'];
340
- }
341
- if (action['skip-test-files']) {
342
- action.skipTestFiles = action['skip-test-files'] === 'true';
343
- delete action['skip-test-files'];
344
- }
345
-
346
- actions.push(action);
347
- }
348
-
349
- // Extract self-closing <security-scan-project> tags
350
- const securityScanProjectPattern = /<security-scan-project\s+(.+?)\/>/g;
351
-
352
- while ((match = securityScanProjectPattern.exec(content)) !== null) {
353
- const attributeString = match[1].trim();
354
- const parser = new TagParser();
355
- const attributes = parser.parseAttributes(attributeString);
356
-
357
- const action = {
358
- type: 'security-scan-project',
359
- ...attributes
360
- };
361
-
362
- // Normalize attribute names
363
- if (action['skip-test-files']) {
364
- action.skipTestFiles = action['skip-test-files'] === 'true';
365
- delete action['skip-test-files'];
366
- }
367
-
368
- actions.push(action);
369
- }
370
-
371
- // Extract self-closing <validate-config> tags
372
- const validateConfigPattern = /<validate-config\s+(.+?)\/>/g;
373
-
374
- while ((match = validateConfigPattern.exec(content)) !== null) {
375
- const attributeString = match[1].trim();
376
- const parser = new TagParser();
377
- const attributes = parser.parseAttributes(attributeString);
378
-
379
- const action = {
380
- type: 'validate-config',
381
- ...attributes
382
- };
383
-
384
- // Normalize attribute names
385
- if (action['file-path']) {
386
- action.filePath = action['file-path'];
387
- delete action['file-path'];
388
- }
389
-
390
- actions.push(action);
391
- }
392
-
393
- // Extract self-closing <validate-config-directory> tags
394
- const validateConfigDirPattern = /<validate-config-directory\s+(.+?)\/>/g;
395
-
396
- while ((match = validateConfigDirPattern.exec(content)) !== null) {
397
- const attributeString = match[1].trim();
398
- const parser = new TagParser();
399
- const attributes = parser.parseAttributes(attributeString);
400
-
401
- const action = {
402
- type: 'validate-config-directory',
403
- ...attributes
404
- };
405
-
406
- // Normalize attribute names (none specific yet)
407
-
408
- actions.push(action);
409
- }
410
-
411
- params.actions = actions;
412
- params.rawContent = content.trim();
413
-
414
- this.logger?.debug('Parsed StaticAnalysis tool parameters', {
415
- totalActions: actions.length,
416
- actionTypes: actions.map(a => a.type)
417
- });
418
-
419
- return params;
420
-
421
- } catch (error) {
422
- throw new Error(`Failed to parse static analysis parameters: ${error.message}`);
423
- }
424
- }
425
-
426
- /**
427
- * Get required parameters
428
- * @returns {Array<string>} Array of required parameter names
429
- */
430
- getRequiredParameters() {
431
- return ['actions'];
432
- }
433
-
434
- /**
435
- * Custom parameter validation
436
- * @param {Object} params - Parameters to validate
437
- * @returns {Object} Validation result
438
- */
439
- customValidateParameters(params) {
440
- const errors = [];
441
-
442
- if (!params.actions || !Array.isArray(params.actions) || params.actions.length === 0) {
443
- errors.push('At least one action is required');
444
- } else {
445
- // Validate each action
446
- for (const [index, action] of params.actions.entries()) {
447
- if (!action.type) {
448
- errors.push(`Action ${index + 1}: type is required`);
449
- continue;
450
- }
451
-
452
- switch (action.type) {
453
- case 'analyze':
454
- if (!action.filePath) {
455
- errors.push(`Action ${index + 1}: file-path is required for analyze`);
456
- }
457
- break;
458
-
459
- case 'analyze-project':
460
- if (!action.directory) {
461
- errors.push(`Action ${index + 1}: directory is required for analyze-project`);
462
- }
463
- break;
464
-
465
- case 'fix':
466
- if (!action.filePath) {
467
- errors.push(`Action ${index + 1}: file-path is required for fix`);
468
- }
469
- break;
470
-
471
- case 'format':
472
- if (!action.filePath) {
473
- errors.push(`Action ${index + 1}: file-path is required for format`);
474
- }
475
- break;
476
-
477
- case 'security-scan':
478
- if (!action.filePath) {
479
- errors.push(`Action ${index + 1}: file-path is required for security-scan`);
480
- }
481
- break;
482
-
483
- case 'security-scan-project':
484
- if (!action.directory) {
485
- errors.push(`Action ${index + 1}: directory is required for security-scan-project`);
486
- }
487
- break;
488
-
489
- case 'validate-config':
490
- if (!action.filePath) {
491
- errors.push(`Action ${index + 1}: file-path is required for validate-config`);
492
- }
493
- break;
494
-
495
- case 'validate-config-directory':
496
- if (!action.directory) {
497
- errors.push(`Action ${index + 1}: directory is required for validate-config-directory`);
498
- }
499
- break;
500
-
501
- default:
502
- errors.push(`Action ${index + 1}: unknown action type: ${action.type}`);
503
- }
504
- }
505
-
506
- // Check batch size limit
507
- if (params.actions.length > this.maxFilesPerBatch) {
508
- errors.push(`Too many actions: ${params.actions.length} (max ${this.maxFilesPerBatch})`);
509
- }
510
- }
511
-
512
- return {
513
- valid: errors.length === 0,
514
- errors
515
- };
516
- }
517
-
518
- /**
519
- * Execute tool with parsed parameters
520
- * @param {Object} params - Parsed parameters
521
- * @param {Object} context - Execution context
522
- * @returns {Promise<Object>} Execution result
523
- */
524
- async execute(params, context) {
525
- const { actions } = params;
526
- const { projectDir, agentId, directoryAccess } = context;
527
-
528
- // Get directory access configuration
529
- const accessConfig = directoryAccess ||
530
- this.directoryAccessManager.createDirectoryAccess({
531
- workingDirectory: projectDir || process.cwd(),
532
- writeEnabledDirectories: [projectDir || process.cwd()],
533
- restrictToProject: true
534
- });
535
-
536
- const workingDir = this.directoryAccessManager.getWorkingDirectory(accessConfig);
537
- const results = {
538
- files: [],
539
- summary: {
540
- totalFiles: 0,
541
- totalErrors: 0,
542
- totalWarnings: 0,
543
- totalInfo: 0,
544
- errorsByCategory: {},
545
- filesByLanguage: {},
546
- filesWithErrors: 0
547
- }
548
- };
549
-
550
- for (const action of actions) {
551
- try {
552
- let actionResult;
553
-
554
- switch (action.type) {
555
- case 'analyze':
556
- actionResult = await this.analyzeFile(action.filePath, workingDir, accessConfig, action);
557
- if (actionResult) {
558
- results.files.push(actionResult);
559
- this.updateSummary(results.summary, actionResult);
560
- }
561
- break;
562
-
563
- case 'analyze-project':
564
- const projectFiles = await this.analyzeProject(action.directory, action.pattern, workingDir, accessConfig, action);
565
- results.files.push(...projectFiles);
566
- for (const fileResult of projectFiles) {
567
- this.updateSummary(results.summary, fileResult);
568
- }
569
- break;
570
-
571
- case 'fix':
572
- actionResult = await this.fixFile(action.filePath, workingDir, accessConfig, action);
573
- if (actionResult) {
574
- results.files.push(actionResult);
575
- }
576
- break;
577
-
578
- case 'format':
579
- actionResult = await this.formatFile(action.filePath, workingDir, accessConfig, action);
580
- if (actionResult) {
581
- results.files.push(actionResult);
582
- }
583
- break;
584
-
585
- case 'security-scan':
586
- actionResult = await this.securityScanFile(action.filePath, workingDir, accessConfig, action);
587
- if (actionResult) {
588
- results.files.push(actionResult);
589
- this.updateSummary(results.summary, actionResult);
590
- }
591
- break;
592
-
593
- case 'security-scan-project':
594
- const securityProjectFiles = await this.securityScanProject(action.directory, action.pattern, workingDir, accessConfig, action);
595
- results.files.push(...securityProjectFiles);
596
- for (const fileResult of securityProjectFiles) {
597
- this.updateSummary(results.summary, fileResult);
598
- }
599
- break;
600
-
601
- case 'validate-config':
602
- actionResult = await this.validateConfigFile(action.filePath, workingDir, accessConfig, action);
603
- if (actionResult) {
604
- results.files.push(actionResult);
605
- this.updateSummary(results.summary, actionResult);
606
- }
607
- break;
608
-
609
- case 'validate-config-directory':
610
- const configFiles = await this.validateConfigDirectory(action.directory, workingDir, accessConfig, action);
611
- results.files.push(...configFiles);
612
- for (const fileResult of configFiles) {
613
- this.updateSummary(results.summary, fileResult);
614
- }
615
- break;
616
-
617
- default:
618
- throw new Error(`Unknown action type: ${action.type}`);
619
- }
620
-
621
- } catch (error) {
622
- this.logger?.error('Static analysis action failed', {
623
- action: action.type,
624
- error: error.message
625
- });
626
-
627
- results.files.push({
628
- file: action.filePath || action.directory,
629
- error: error.message,
630
- success: false
631
- });
632
- }
633
- }
634
-
635
- return {
636
- success: true,
637
- results,
638
- toolUsed: 'staticanalysis',
639
- performance: this.getPerformanceMetrics()
640
- };
641
- }
642
-
643
- /**
644
- * Analyze a single file
645
- * @private
646
- */
647
- async analyzeFile(filePath, workingDir, accessConfig, options = {}) {
648
- const fullPath = path.isAbsolute(filePath)
649
- ? path.normalize(filePath)
650
- : path.resolve(workingDir, filePath);
651
-
652
- // Validate read access
653
- const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
654
- if (!accessResult.allowed) {
655
- throw new Error(`Read access denied: ${accessResult.reason}`);
656
- }
657
-
658
- // Check file exists
659
- try {
660
- const stats = await fs.stat(fullPath);
661
-
662
- if (stats.size > this.maxFileSize) {
663
- throw new Error(`File too large: ${stats.size} bytes (max ${this.maxFileSize})`);
664
- }
665
-
666
- // Detect language from file extension
667
- const language = this.detectLanguage(fullPath);
668
-
669
- if (!language) {
670
- return {
671
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
672
- fullPath,
673
- language: 'unknown',
674
- errors: [],
675
- warnings: [],
676
- info: [],
677
- skipped: true,
678
- skipReason: 'Unsupported file type'
679
- };
680
- }
681
-
682
- // Read file content
683
- const content = await fs.readFile(fullPath, 'utf-8');
684
-
685
- // Check cache (use content hash for more accurate caching)
686
- const contentHash = this.useContentHash ? this.computeContentHash(content) : null;
687
- const cacheKey = this.useContentHash
688
- ? `${fullPath}:${contentHash}`
689
- : `${fullPath}:${stats.mtime.getTime()}`;
690
-
691
- if (this.enableCache && this.analysisCache.has(cacheKey)) {
692
- const cached = this.analysisCache.get(cacheKey);
693
- if (Date.now() - cached.timestamp < this.cacheExpiry) {
694
- this.logger?.debug('Using cached analysis result', { file: fullPath });
695
- this.metrics.cacheHits++;
696
- this.metrics.totalAnalyses++;
697
- return cached.result;
698
- }
699
- }
700
-
701
- this.metrics.cacheMisses++;
702
- this.metrics.totalAnalyses++;
703
-
704
- // Get analyzer for language
705
- const analyzer = await this.getAnalyzer(language);
706
-
707
- if (!analyzer) {
708
- return {
709
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
710
- fullPath,
711
- language,
712
- errors: [],
713
- warnings: [],
714
- info: [],
715
- skipped: true,
716
- skipReason: `No analyzer available for ${language}`
717
- };
718
- }
719
-
720
- // Perform analysis with timing
721
- const analysisStart = Date.now();
722
- const diagnostics = await analyzer.analyze(fullPath, content, {
723
- workingDir,
724
- accessConfig,
725
- framework: await this.detectFramework(workingDir, language)
726
- });
727
- const analysisTime = Date.now() - analysisStart;
728
-
729
- this.metrics.totalAnalysisTime += analysisTime;
730
- this.metrics.filesAnalyzed++;
731
-
732
- // Format results
733
- const result = {
734
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
735
- fullPath,
736
- language,
737
- framework: await this.detectFramework(workingDir, language),
738
- errors: diagnostics.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.ERROR),
739
- warnings: options.includeWarnings !== false
740
- ? diagnostics.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.WARNING)
741
- : [],
742
- info: diagnostics.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.INFO),
743
- totalIssues: diagnostics.length,
744
- analyzed: true,
745
- timestamp: new Date().toISOString()
746
- };
747
-
748
- // Apply max errors limit
749
- if (options.maxErrors && result.errors.length > options.maxErrors) {
750
- result.errors = result.errors.slice(0, options.maxErrors);
751
- result.truncated = true;
752
- }
753
-
754
- // Cache result
755
- if (this.enableCache) {
756
- this.analysisCache.set(cacheKey, {
757
- result,
758
- timestamp: Date.now()
759
- });
760
- }
761
-
762
- return result;
763
-
764
- } catch (error) {
765
- throw new Error(`Failed to analyze ${filePath}: ${error.message}`);
766
- }
767
- }
768
-
769
- /**
770
- * Analyze project directory
771
- * @private
772
- */
773
- async analyzeProject(directory, pattern, workingDir, accessConfig, options = {}) {
774
- const fullDir = path.isAbsolute(directory)
775
- ? path.normalize(directory)
776
- : path.resolve(workingDir, directory);
777
-
778
- // Validate read access
779
- const accessResult = this.directoryAccessManager.validateReadAccess(fullDir, accessConfig);
780
- if (!accessResult.allowed) {
781
- throw new Error(`Read access denied: ${accessResult.reason}`);
782
- }
783
-
784
- // Find all matching files
785
- const files = await this.findFiles(fullDir, pattern);
786
-
787
- if (files.length > this.maxFilesPerBatch) {
788
- throw new Error(`Too many files: ${files.length} (max ${this.maxFilesPerBatch})`);
789
- }
790
-
791
- // Analyze files (parallel or sequential based on configuration)
792
- const results = [];
793
-
794
- if (this.parallelAnalysis && files.length > 1) {
795
- // Parallel analysis in batches
796
- this.logger?.debug('Using parallel analysis', {
797
- totalFiles: files.length,
798
- batchSize: this.maxParallelFiles
799
- });
800
-
801
- for (let i = 0; i < files.length; i += this.maxParallelFiles) {
802
- const batch = files.slice(i, i + this.maxParallelFiles);
803
- this.metrics.parallelBatches++;
804
-
805
- // Report progress
806
- const progress = {
807
- completed: i,
808
- total: files.length,
809
- percentage: Math.round((i / files.length) * 100)
810
- };
811
-
812
- if (options.onProgress) {
813
- options.onProgress(progress);
814
- }
815
-
816
- this.logger?.debug('Analyzing batch', {
817
- batch: Math.floor(i / this.maxParallelFiles) + 1,
818
- filesInBatch: batch.length,
819
- progress: `${progress.completed}/${progress.total}`
820
- });
821
-
822
- // Analyze batch in parallel
823
- const batchPromises = batch.map(async (file) => {
824
- try {
825
- const result = await this.analyzeFile(file, workingDir, accessConfig, options);
826
- return result;
827
- } catch (error) {
828
- this.logger?.warn('Failed to analyze file in project', {
829
- file,
830
- error: error.message
831
- });
832
-
833
- return {
834
- file: this.directoryAccessManager.createRelativePath(file, accessConfig),
835
- fullPath: file,
836
- error: error.message,
837
- success: false
838
- };
839
- }
840
- });
841
-
842
- const batchResults = await Promise.all(batchPromises);
843
- results.push(...batchResults.filter(r => r !== null));
844
- }
845
-
846
- // Final progress report
847
- if (options.onProgress) {
848
- options.onProgress({
849
- completed: files.length,
850
- total: files.length,
851
- percentage: 100
852
- });
853
- }
854
-
855
- } else {
856
- // Sequential analysis
857
- for (const file of files) {
858
- try {
859
- const result = await this.analyzeFile(file, workingDir, accessConfig, options);
860
- if (result) {
861
- results.push(result);
862
- }
863
- } catch (error) {
864
- this.logger?.warn('Failed to analyze file in project', {
865
- file,
866
- error: error.message
867
- });
868
-
869
- results.push({
870
- file: this.directoryAccessManager.createRelativePath(file, accessConfig),
871
- fullPath: file,
872
- error: error.message,
873
- success: false
874
- });
875
- }
876
- }
877
- }
878
-
879
- return results;
880
- }
881
-
882
- /**
883
- * Fix code issues in a file
884
- * @private
885
- */
886
- async fixFile(filePath, workingDir, accessConfig, options = {}) {
887
- const fullPath = path.isAbsolute(filePath)
888
- ? path.normalize(filePath)
889
- : path.resolve(workingDir, filePath);
890
-
891
- // Validate read access
892
- const readResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
893
- if (!readResult.allowed) {
894
- throw new Error(`Read access denied: ${readResult.reason}`);
895
- }
896
-
897
- // Validate write access if writeFile is true
898
- if (options.writeFile) {
899
- const writeResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
900
- if (!writeResult.allowed) {
901
- throw new Error(`Write access denied: ${writeResult.reason}`);
902
- }
903
- }
904
-
905
- try {
906
- // Read file
907
- const content = await fs.readFile(fullPath, 'utf-8');
908
-
909
- // Get ESLint analyzer
910
- const eslintAnalyzer = await this.getESLintAnalyzer();
911
-
912
- // Fix the code
913
- const fixResult = await eslintAnalyzer.fix(fullPath, content, {
914
- workingDir,
915
- accessConfig,
916
- framework: await this.detectFramework(workingDir, this.detectLanguage(fullPath))
917
- });
918
-
919
- // Write file if requested and changes were made
920
- if (options.writeFile && fixResult.fixed) {
921
- await fs.writeFile(fullPath, fixResult.content, 'utf-8');
922
- this.logger?.info('File fixed and written', { file: fullPath });
923
- }
924
-
925
- return {
926
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
927
- fullPath,
928
- action: 'fix',
929
- fixed: fixResult.fixed,
930
- fixedCount: fixResult.fixedCount,
931
- remainingErrors: fixResult.remainingErrors,
932
- remainingWarnings: fixResult.remainingWarnings,
933
- changes: fixResult.changes,
934
- written: !!(options.writeFile && fixResult.fixed),
935
- preview: !options.writeFile && fixResult.fixed ? fixResult.content : undefined
936
- };
937
-
938
- } catch (error) {
939
- throw new Error(`Failed to fix ${filePath}: ${error.message}`);
940
- }
941
- }
942
-
943
- /**
944
- * Format code in a file
945
- * @private
946
- */
947
- async formatFile(filePath, workingDir, accessConfig, options = {}) {
948
- const fullPath = path.isAbsolute(filePath)
949
- ? path.normalize(filePath)
950
- : path.resolve(workingDir, filePath);
951
-
952
- // Validate read access
953
- const readResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
954
- if (!readResult.allowed) {
955
- throw new Error(`Read access denied: ${readResult.reason}`);
956
- }
957
-
958
- // Validate write access if writeFile is true
959
- if (options.writeFile) {
960
- const writeResult = this.directoryAccessManager.validateWriteAccess(fullPath, accessConfig);
961
- if (!writeResult.allowed) {
962
- throw new Error(`Write access denied: ${writeResult.reason}`);
963
- }
964
- }
965
-
966
- try {
967
- // Read file
968
- const content = await fs.readFile(fullPath, 'utf-8');
969
-
970
- // Get Prettier formatter
971
- const prettierFormatter = await this.getPrettierFormatter();
972
-
973
- // Check if file type is supported
974
- if (!prettierFormatter.isSupported(fullPath)) {
975
- return {
976
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
977
- fullPath,
978
- action: 'format',
979
- formatted: false,
980
- skipped: true,
981
- skipReason: 'File type not supported by Prettier'
982
- };
983
- }
984
-
985
- // Format the code
986
- const formatResult = await prettierFormatter.format(fullPath, content, {
987
- workingDir,
988
- accessConfig
989
- });
990
-
991
- // Write file if requested and changes were made
992
- if (options.writeFile && formatResult.formatted) {
993
- await fs.writeFile(fullPath, formatResult.content, 'utf-8');
994
- this.logger?.info('File formatted and written', { file: fullPath });
995
- }
996
-
997
- return {
998
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
999
- fullPath,
1000
- action: 'format',
1001
- formatted: formatResult.formatted,
1002
- linesChanged: formatResult.linesChanged,
1003
- changes: formatResult.changes,
1004
- written: !!(options.writeFile && formatResult.formatted),
1005
- preview: !options.writeFile && formatResult.formatted ? formatResult.content : undefined
1006
- };
1007
-
1008
- } catch (error) {
1009
- throw new Error(`Failed to format ${filePath}: ${error.message}`);
1010
- }
1011
- }
1012
-
1013
- /**
1014
- * Security scan a single file
1015
- * @private
1016
- */
1017
- async securityScanFile(filePath, workingDir, accessConfig, options = {}) {
1018
- const fullPath = path.isAbsolute(filePath)
1019
- ? path.normalize(filePath)
1020
- : path.resolve(workingDir, filePath);
1021
-
1022
- // Validate read access
1023
- const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
1024
- if (!accessResult.allowed) {
1025
- throw new Error(`Read access denied: ${accessResult.reason}`);
1026
- }
1027
-
1028
- try {
1029
- const stats = await fs.stat(fullPath);
1030
-
1031
- if (stats.size > this.maxFileSize) {
1032
- throw new Error(`File too large: ${stats.size} bytes (max ${this.maxFileSize})`);
1033
- }
1034
-
1035
- // Detect language
1036
- const language = this.detectLanguage(fullPath);
1037
-
1038
- // Security analyzer only supports JS/TS/Python
1039
- if (!language || !['javascript', 'typescript', 'python'].includes(language)) {
1040
- return {
1041
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
1042
- fullPath,
1043
- language: language || 'unknown',
1044
- issues: [],
1045
- skipped: true,
1046
- skipReason: 'Security scanning only supports JavaScript, TypeScript, and Python files'
1047
- };
1048
- }
1049
-
1050
- // Read file content
1051
- const content = await fs.readFile(fullPath, 'utf-8');
1052
-
1053
- // Get security analyzer
1054
- const securityAnalyzer = await this.getSecurityAnalyzer();
1055
-
1056
- // Perform security scan
1057
- const issues = await securityAnalyzer.analyze(fullPath, content, {
1058
- skipTestFiles: options.skipTestFiles !== false
1059
- });
1060
-
1061
- // Categorize issues by severity
1062
- const result = {
1063
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
1064
- fullPath,
1065
- language,
1066
- action: 'security-scan',
1067
- critical: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.CRITICAL),
1068
- errors: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.ERROR),
1069
- warnings: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.WARNING),
1070
- info: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.INFO),
1071
- totalIssues: issues.length,
1072
- analyzed: true,
1073
- scannersUsed: issues.map(i => i.scanner).filter((v, i, a) => a.indexOf(v) === i),
1074
- timestamp: new Date().toISOString()
1075
- };
1076
-
1077
- return result;
1078
-
1079
- } catch (error) {
1080
- throw new Error(`Failed to security scan ${filePath}: ${error.message}`);
1081
- }
1082
- }
1083
-
1084
- /**
1085
- * Security scan project directory
1086
- * @private
1087
- */
1088
- async securityScanProject(directory, pattern, workingDir, accessConfig, options = {}) {
1089
- const fullDir = path.isAbsolute(directory)
1090
- ? path.normalize(directory)
1091
- : path.resolve(workingDir, directory);
1092
-
1093
- // Validate read access
1094
- const accessResult = this.directoryAccessManager.validateReadAccess(fullDir, accessConfig);
1095
- if (!accessResult.allowed) {
1096
- throw new Error(`Read access denied: ${accessResult.reason}`);
1097
- }
1098
-
1099
- // Get security analyzer for dependency scanning
1100
- const securityAnalyzer = await this.getSecurityAnalyzer();
1101
-
1102
- // Run dependency scans at project level
1103
- const dependencyIssues = await securityAnalyzer.analyzeProject(fullDir, 'javascript', options);
1104
-
1105
- // Find all matching files (only JS/TS/Python for security scanning)
1106
- const searchPattern = pattern || '**/*.{js,jsx,mjs,cjs,ts,tsx,py}';
1107
- const files = await this.findFiles(fullDir, searchPattern);
1108
-
1109
- if (files.length > this.maxFilesPerBatch) {
1110
- throw new Error(`Too many files: ${files.length} (max ${this.maxFilesPerBatch})`);
1111
- }
1112
-
1113
- // Scan files (parallel or sequential)
1114
- const results = [];
1115
-
1116
- if (this.parallelAnalysis && files.length > 1) {
1117
- // Parallel scanning in batches
1118
- this.logger?.debug('Using parallel security scanning', {
1119
- totalFiles: files.length,
1120
- batchSize: this.maxParallelFiles
1121
- });
1122
-
1123
- for (let i = 0; i < files.length; i += this.maxParallelFiles) {
1124
- const batch = files.slice(i, i + this.maxParallelFiles);
1125
-
1126
- if (options.onProgress) {
1127
- options.onProgress({
1128
- completed: i,
1129
- total: files.length,
1130
- percentage: Math.round((i / files.length) * 100)
1131
- });
1132
- }
1133
-
1134
- const batchPromises = batch.map(async (file) => {
1135
- try {
1136
- return await this.securityScanFile(file, workingDir, accessConfig, options);
1137
- } catch (error) {
1138
- this.logger?.warn('Failed to security scan file in project', {
1139
- file,
1140
- error: error.message
1141
- });
1142
-
1143
- return {
1144
- file: this.directoryAccessManager.createRelativePath(file, accessConfig),
1145
- fullPath: file,
1146
- error: error.message,
1147
- success: false
1148
- };
1149
- }
1150
- });
1151
-
1152
- const batchResults = await Promise.all(batchPromises);
1153
- results.push(...batchResults.filter(r => r !== null));
1154
- }
1155
-
1156
- if (options.onProgress) {
1157
- options.onProgress({
1158
- completed: files.length,
1159
- total: files.length,
1160
- percentage: 100
1161
- });
1162
- }
1163
-
1164
- } else {
1165
- // Sequential scanning
1166
- for (const file of files) {
1167
- try {
1168
- const result = await this.securityScanFile(file, workingDir, accessConfig, options);
1169
- if (result) {
1170
- results.push(result);
1171
- }
1172
- } catch (error) {
1173
- this.logger?.warn('Failed to security scan file in project', {
1174
- file,
1175
- error: error.message
1176
- });
1177
-
1178
- results.push({
1179
- file: this.directoryAccessManager.createRelativePath(file, accessConfig),
1180
- fullPath: file,
1181
- error: error.message,
1182
- success: false
1183
- });
1184
- }
1185
- }
1186
- }
1187
-
1188
- // Add dependency scan results if any
1189
- if (dependencyIssues.length > 0) {
1190
- results.push({
1191
- file: path.join(fullDir, 'package.json'),
1192
- fullPath: path.join(fullDir, 'package.json'),
1193
- action: 'dependency-scan',
1194
- critical: dependencyIssues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.CRITICAL),
1195
- errors: dependencyIssues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.ERROR),
1196
- warnings: dependencyIssues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.WARNING),
1197
- info: dependencyIssues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.INFO),
1198
- totalIssues: dependencyIssues.length,
1199
- analyzed: true,
1200
- scannersUsed: ['npm-audit'],
1201
- timestamp: new Date().toISOString()
1202
- });
1203
- }
1204
-
1205
- return results;
1206
- }
1207
-
1208
- /**
1209
- * Validate a configuration file
1210
- * @private
1211
- */
1212
- async validateConfigFile(filePath, workingDir, accessConfig, options = {}) {
1213
- const fullPath = path.isAbsolute(filePath)
1214
- ? path.normalize(filePath)
1215
- : path.resolve(workingDir, filePath);
1216
-
1217
- // Validate read access
1218
- const accessResult = this.directoryAccessManager.validateReadAccess(fullPath, accessConfig);
1219
- if (!accessResult.allowed) {
1220
- throw new Error(`Read access denied: ${accessResult.reason}`);
1221
- }
1222
-
1223
- try {
1224
- const stats = await fs.stat(fullPath);
1225
-
1226
- if (stats.size > this.maxFileSize) {
1227
- throw new Error(`File too large: ${stats.size} bytes (max ${this.maxFileSize})`);
1228
- }
1229
-
1230
- // Get config validator
1231
- const configValidator = await this.getConfigValidator();
1232
-
1233
- // Perform validation
1234
- const issues = await configValidator.validate(fullPath, options);
1235
-
1236
- // Categorize issues by severity
1237
- const result = {
1238
- file: this.directoryAccessManager.createRelativePath(fullPath, accessConfig),
1239
- fullPath,
1240
- action: 'validate-config',
1241
- critical: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.CRITICAL),
1242
- errors: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.ERROR),
1243
- warnings: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.WARNING),
1244
- info: issues.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.INFO),
1245
- totalIssues: issues.length,
1246
- analyzed: true,
1247
- validatorsUsed: issues.map(i => i.validator).filter((v, i, a) => a.indexOf(v) === i),
1248
- timestamp: new Date().toISOString()
1249
- };
1250
-
1251
- return result;
1252
-
1253
- } catch (error) {
1254
- throw new Error(`Failed to validate config ${filePath}: ${error.message}`);
1255
- }
1256
- }
1257
-
1258
- /**
1259
- * Validate configuration files in a directory
1260
- * @private
1261
- */
1262
- async validateConfigDirectory(directory, workingDir, accessConfig, options = {}) {
1263
- const fullDir = path.isAbsolute(directory)
1264
- ? path.normalize(directory)
1265
- : path.resolve(workingDir, directory);
1266
-
1267
- // Validate read access
1268
- const accessResult = this.directoryAccessManager.validateReadAccess(fullDir, accessConfig);
1269
- if (!accessResult.allowed) {
1270
- throw new Error(`Read access denied: ${accessResult.reason}`);
1271
- }
1272
-
1273
- // Find common config files
1274
- const configFiles = await this.findConfigFiles(fullDir);
1275
-
1276
- if (configFiles.length > this.maxFilesPerBatch) {
1277
- throw new Error(`Too many config files: ${configFiles.length} (max ${this.maxFilesPerBatch})`);
1278
- }
1279
-
1280
- // Validate files
1281
- const results = [];
1282
-
1283
- for (const file of configFiles) {
1284
- try {
1285
- const result = await this.validateConfigFile(file, workingDir, accessConfig, options);
1286
- if (result) {
1287
- results.push(result);
1288
- }
1289
- } catch (error) {
1290
- this.logger?.warn('Failed to validate config file', {
1291
- file,
1292
- error: error.message
1293
- });
1294
-
1295
- results.push({
1296
- file: this.directoryAccessManager.createRelativePath(file, accessConfig),
1297
- fullPath: file,
1298
- error: error.message,
1299
- success: false
1300
- });
1301
- }
1302
- }
1303
-
1304
- return results;
1305
- }
1306
-
1307
- /**
1308
- * Find common configuration files in directory
1309
- * @private
1310
- */
1311
- async findConfigFiles(directory) {
1312
- const files = [];
1313
- const configFileNames = [
1314
- 'package.json',
1315
- 'tsconfig.json',
1316
- 'Dockerfile',
1317
- 'docker-compose.yml',
1318
- 'docker-compose.yaml',
1319
- '.env',
1320
- '.env.example',
1321
- '.eslintrc.js',
1322
- '.eslintrc.json',
1323
- '.prettierrc',
1324
- '.prettierrc.json'
1325
- ];
1326
-
1327
- const configExtensions = ['.yml', '.yaml', '.json', '.tf', '.tfvars'];
1328
-
1329
- const walk = async (dir) => {
1330
- const entries = await fs.readdir(dir, { withFileTypes: true });
1331
-
1332
- for (const entry of entries) {
1333
- const fullPath = path.join(dir, entry.name);
1334
-
1335
- if (entry.isDirectory()) {
1336
- // Check specific directories for config files
1337
- if (entry.name === '.github' || entry.name === 'kubernetes' || entry.name === 'k8s' || entry.name === 'terraform') {
1338
- await walk(fullPath);
1339
- } else if (!['node_modules', '.git', 'dist', 'build'].includes(entry.name)) {
1340
- // Don't recurse into all subdirectories, only known config dirs
1341
- // Check this level only
1342
- continue;
1343
- }
1344
- } else if (entry.isFile()) {
1345
- // Check if it's a known config file
1346
- if (configFileNames.includes(entry.name)) {
1347
- files.push(fullPath);
1348
- } else {
1349
- // Check if it's in a config directory with config extension
1350
- const ext = path.extname(entry.name).toLowerCase();
1351
- if (configExtensions.includes(ext)) {
1352
- const dirname = path.basename(path.dirname(fullPath));
1353
- if (dirname === 'kubernetes' || dirname === 'k8s' || dirname === 'terraform' || dirname === 'workflows') {
1354
- files.push(fullPath);
1355
- }
1356
- }
1357
- }
1358
- }
1359
- }
1360
- };
1361
-
1362
- await walk(directory);
1363
- return files;
1364
- }
1365
-
1366
- /**
1367
- * Detect programming language from file extension
1368
- * @private
1369
- */
1370
- detectLanguage(filePath) {
1371
- const ext = path.extname(filePath).toLowerCase();
1372
- return STATIC_ANALYSIS.EXTENSION_TO_LANGUAGE[ext] || null;
1373
- }
1374
-
1375
- /**
1376
- * Detect framework from project directory
1377
- * @private
1378
- */
1379
- async detectFramework(projectDir, language) {
1380
- try {
1381
- if (language === STATIC_ANALYSIS.LANGUAGE.JAVASCRIPT ||
1382
- language === STATIC_ANALYSIS.LANGUAGE.TYPESCRIPT) {
1383
- return await this.detectJSFramework(projectDir);
1384
- }
1385
-
1386
- if (language === STATIC_ANALYSIS.LANGUAGE.PYTHON) {
1387
- return await this.detectPythonFramework(projectDir);
1388
- }
1389
-
1390
- return null;
1391
- } catch (error) {
1392
- this.logger?.debug('Framework detection failed', { error: error.message });
1393
- return null;
1394
- }
1395
- }
1396
-
1397
- /**
1398
- * Detect JavaScript/TypeScript framework
1399
- * @private
1400
- */
1401
- async detectJSFramework(projectDir) {
1402
- try {
1403
- const pkgPath = path.join(projectDir, STATIC_ANALYSIS.FRAMEWORK_MANIFESTS.JAVASCRIPT);
1404
- const pkgContent = await fs.readFile(pkgPath, 'utf-8');
1405
- const pkg = JSON.parse(pkgContent);
1406
-
1407
- const deps = {
1408
- ...pkg.dependencies,
1409
- ...pkg.devDependencies
1410
- };
1411
-
1412
- // Check for frameworks in priority order
1413
- for (const [name, identifier] of Object.entries(STATIC_ANALYSIS.JS_FRAMEWORKS)) {
1414
- if (deps[identifier]) {
1415
- return name.toLowerCase();
1416
- }
1417
- }
1418
-
1419
- return null;
1420
- } catch (error) {
1421
- return null;
1422
- }
1423
- }
1424
-
1425
- /**
1426
- * Detect Python framework
1427
- * @private
1428
- */
1429
- async detectPythonFramework(projectDir) {
1430
- try {
1431
- // Try requirements.txt
1432
- const reqPath = path.join(projectDir, STATIC_ANALYSIS.FRAMEWORK_MANIFESTS.PYTHON);
1433
- const reqContent = await fs.readFile(reqPath, 'utf-8');
1434
-
1435
- // Check for frameworks
1436
- for (const [name, identifier] of Object.entries(STATIC_ANALYSIS.PYTHON_FRAMEWORKS)) {
1437
- if (reqContent.toLowerCase().includes(identifier)) {
1438
- return name.toLowerCase();
1439
- }
1440
- }
1441
-
1442
- return null;
1443
- } catch (error) {
1444
- // Try pyproject.toml
1445
- try {
1446
- const tomlPath = path.join(projectDir, STATIC_ANALYSIS.FRAMEWORK_MANIFESTS.PYTHON_POETRY);
1447
- const tomlContent = await fs.readFile(tomlPath, 'utf-8');
1448
-
1449
- for (const [name, identifier] of Object.entries(STATIC_ANALYSIS.PYTHON_FRAMEWORKS)) {
1450
- if (tomlContent.toLowerCase().includes(identifier)) {
1451
- return name.toLowerCase();
1452
- }
1453
- }
1454
- } catch {
1455
- // No framework detected
1456
- }
1457
-
1458
- return null;
1459
- }
1460
- }
1461
-
1462
- /**
1463
- * Find files matching pattern in directory
1464
- * @private
1465
- */
1466
- async findFiles(directory, pattern) {
1467
- const files = [];
1468
-
1469
- // Default patterns by language if not specified
1470
- const searchPattern = pattern || '**/*.{js,jsx,mjs,cjs,ts,tsx,py,css,scss,sass,less}';
1471
-
1472
- // Parse pattern to extract extensions
1473
- // Supports patterns like "**/*.ts", "**/*.{js,ts}", "*.js", etc.
1474
- const getExtensionsFromPattern = (pat) => {
1475
- const exts = [];
1476
-
1477
- // Match patterns like *.{js,ts,tsx} or *.js
1478
- const bracesMatch = pat.match(/\*\.\{([^}]+)\}/);
1479
- if (bracesMatch) {
1480
- // Multiple extensions: *.{js,ts,tsx}
1481
- const extList = bracesMatch[1].split(',').map(e => e.trim());
1482
- extList.forEach(ext => exts.push(ext.startsWith('.') ? ext : '.' + ext));
1483
- } else {
1484
- // Single extension: *.js or **/*.ts
1485
- const singleMatch = pat.match(/\*\.([a-z]+)$/i);
1486
- if (singleMatch) {
1487
- const ext = singleMatch[1];
1488
- exts.push(ext.startsWith('.') ? ext : '.' + ext);
1489
- }
1490
- }
1491
-
1492
- // If no pattern found, allow all supported extensions
1493
- if (exts.length === 0) {
1494
- return null; // null means "all supported extensions"
1495
- }
1496
-
1497
- return exts;
1498
- };
1499
-
1500
- const allowedExtensions = getExtensionsFromPattern(searchPattern);
1501
-
1502
- // Simple recursive file search
1503
- const walk = async (dir) => {
1504
- const entries = await fs.readdir(dir, { withFileTypes: true });
1505
-
1506
- for (const entry of entries) {
1507
- const fullPath = path.join(dir, entry.name);
1508
-
1509
- if (entry.isDirectory()) {
1510
- // Skip common ignore directories
1511
- if (!['node_modules', '.git', 'dist', 'build', '__pycache__', '.venv', 'venv'].includes(entry.name)) {
1512
- await walk(fullPath);
1513
- }
1514
- } else if (entry.isFile()) {
1515
- const ext = path.extname(entry.name).toLowerCase();
1516
-
1517
- // Check if file extension is supported
1518
- if (STATIC_ANALYSIS.EXTENSION_TO_LANGUAGE[ext]) {
1519
- // If pattern specified, check if extension matches
1520
- if (allowedExtensions === null || allowedExtensions.includes(ext)) {
1521
- files.push(fullPath);
1522
- }
1523
- }
1524
- }
1525
- }
1526
- };
1527
-
1528
- await walk(directory);
1529
- return files;
1530
- }
1531
-
1532
- /**
1533
- * Get analyzer for language (lazy initialization)
1534
- * @private
1535
- */
1536
- async getAnalyzer(language) {
1537
- try {
1538
- // Lazy load analyzers
1539
- if (language === STATIC_ANALYSIS.LANGUAGE.JAVASCRIPT) {
1540
- if (!this.analyzers.javascript) {
1541
- const { default: JavaScriptAnalyzer } = await import('../analyzers/JavaScriptAnalyzer.js');
1542
- this.analyzers.javascript = new JavaScriptAnalyzer(this.logger);
1543
- }
1544
- return this.analyzers.javascript;
1545
- }
1546
-
1547
- if (language === STATIC_ANALYSIS.LANGUAGE.TYPESCRIPT) {
1548
- if (!this.analyzers.typescript) {
1549
- const { default: TypeScriptAnalyzer } = await import('../analyzers/TypeScriptAnalyzer.js');
1550
- this.analyzers.typescript = new TypeScriptAnalyzer(this.logger);
1551
- }
1552
- return this.analyzers.typescript;
1553
- }
1554
-
1555
- // Python analyzer
1556
- if (language === STATIC_ANALYSIS.LANGUAGE.PYTHON) {
1557
- if (!this.analyzers.python) {
1558
- const { default: PythonAnalyzer } = await import('../analyzers/PythonAnalyzer.js');
1559
- this.analyzers.python = new PythonAnalyzer(this.logger);
1560
- }
1561
- return this.analyzers.python;
1562
- }
1563
-
1564
- // CSS analyzer (handles CSS, SCSS, LESS)
1565
- if (language === STATIC_ANALYSIS.LANGUAGE.CSS ||
1566
- language === STATIC_ANALYSIS.LANGUAGE.SCSS ||
1567
- language === STATIC_ANALYSIS.LANGUAGE.LESS) {
1568
- if (!this.analyzers.css) {
1569
- const { default: CSSAnalyzer } = await import('../analyzers/CSSAnalyzer.js');
1570
- this.analyzers.css = new CSSAnalyzer(this.logger);
1571
- }
1572
- return this.analyzers.css;
1573
- }
1574
-
1575
- return null;
1576
- } catch (error) {
1577
- this.logger?.error('Failed to load analyzer', {
1578
- language,
1579
- error: error.message
1580
- });
1581
- return null;
1582
- }
1583
- }
1584
-
1585
- /**
1586
- * Get ESLint analyzer (lazy initialization)
1587
- * @private
1588
- */
1589
- async getESLintAnalyzer() {
1590
- if (!this.analyzers.eslint) {
1591
- const { default: ESLintAnalyzer } = await import('../analyzers/ESLintAnalyzer.js');
1592
- this.analyzers.eslint = new ESLintAnalyzer(this.logger);
1593
- }
1594
- return this.analyzers.eslint;
1595
- }
1596
-
1597
- /**
1598
- * Get Prettier formatter (lazy initialization)
1599
- * @private
1600
- */
1601
- async getPrettierFormatter() {
1602
- if (!this.formatters.prettier) {
1603
- const { default: PrettierFormatter } = await import('../analyzers/PrettierFormatter.js');
1604
- this.formatters.prettier = new PrettierFormatter(this.logger);
1605
- }
1606
- return this.formatters.prettier;
1607
- }
1608
-
1609
- /**
1610
- * Get Security analyzer (lazy initialization)
1611
- * @private
1612
- */
1613
- async getSecurityAnalyzer() {
1614
- if (!this.analyzers.security) {
1615
- const { default: SecurityAnalyzer } = await import('../analyzers/SecurityAnalyzer.js');
1616
- this.analyzers.security = new SecurityAnalyzer(this.logger);
1617
- }
1618
- return this.analyzers.security;
1619
- }
1620
-
1621
- /**
1622
- * Get Config validator (lazy initialization)
1623
- * @private
1624
- */
1625
- async getConfigValidator() {
1626
- if (!this.analyzers.config) {
1627
- const { default: ConfigValidator } = await import('../analyzers/ConfigValidator.js');
1628
- this.analyzers.config = new ConfigValidator(this.logger);
1629
- }
1630
- return this.analyzers.config;
1631
- }
1632
-
1633
- /**
1634
- * Update summary statistics
1635
- * @private
1636
- */
1637
- updateSummary(summary, fileResult) {
1638
- if (fileResult.analyzed) {
1639
- summary.totalFiles++;
1640
-
1641
- const criticalCount = fileResult.critical?.length || 0;
1642
- const errorCount = fileResult.errors?.length || 0;
1643
- const warningCount = fileResult.warnings?.length || 0;
1644
- const infoCount = fileResult.info?.length || 0;
1645
-
1646
- // Initialize totalCritical if not exists (for backward compatibility)
1647
- if (summary.totalCritical === undefined) {
1648
- summary.totalCritical = 0;
1649
- }
1650
-
1651
- summary.totalCritical += criticalCount;
1652
- summary.totalErrors += errorCount;
1653
- summary.totalWarnings += warningCount;
1654
- summary.totalInfo += infoCount;
1655
-
1656
- if (criticalCount > 0 || errorCount > 0) {
1657
- summary.filesWithErrors++;
1658
- }
1659
-
1660
- // Count by language
1661
- if (fileResult.language) {
1662
- summary.filesByLanguage[fileResult.language] =
1663
- (summary.filesByLanguage[fileResult.language] || 0) + 1;
1664
- }
1665
-
1666
- // Count by category (include critical issues)
1667
- const allIssues = [
1668
- ...(fileResult.critical || []),
1669
- ...(fileResult.errors || []),
1670
- ...(fileResult.warnings || [])
1671
- ];
1672
-
1673
- for (const issue of allIssues) {
1674
- if (issue.category) {
1675
- summary.errorsByCategory[issue.category] =
1676
- (summary.errorsByCategory[issue.category] || 0) + 1;
1677
- }
1678
- }
1679
- }
1680
- }
1681
-
1682
- /**
1683
- * Compute content hash for caching
1684
- * @private
1685
- */
1686
- computeContentHash(content) {
1687
- return crypto
1688
- .createHash('sha256')
1689
- .update(content)
1690
- .digest('hex')
1691
- .substring(0, 16); // Use first 16 chars for shorter cache keys
1692
- }
1693
-
1694
- /**
1695
- * Get performance metrics
1696
- * @returns {Object} Performance metrics
1697
- */
1698
- getPerformanceMetrics() {
1699
- const cacheHitRate = this.metrics.totalAnalyses > 0
1700
- ? (this.metrics.cacheHits / this.metrics.totalAnalyses) * 100
1701
- : 0;
1702
-
1703
- const avgAnalysisTime = this.metrics.filesAnalyzed > 0
1704
- ? this.metrics.totalAnalysisTime / this.metrics.filesAnalyzed
1705
- : 0;
1706
-
1707
- return {
1708
- ...this.metrics,
1709
- cacheHitRate: Math.round(cacheHitRate * 10) / 10, // Round to 1 decimal
1710
- averageAnalysisTime: Math.round(avgAnalysisTime),
1711
- cacheSize: this.analysisCache.size
1712
- };
1713
- }
1714
-
1715
- /**
1716
- * Reset performance metrics
1717
- */
1718
- resetPerformanceMetrics() {
1719
- this.metrics = {
1720
- totalAnalyses: 0,
1721
- cacheHits: 0,
1722
- cacheMisses: 0,
1723
- totalAnalysisTime: 0,
1724
- filesAnalyzed: 0,
1725
- parallelBatches: 0
1726
- };
1727
- }
1728
-
1729
- /**
1730
- * Clear analysis cache
1731
- */
1732
- clearCache() {
1733
- this.analysisCache.clear();
1734
- this.logger?.debug('Analysis cache cleared');
1735
- }
1736
-
1737
- /**
1738
- * Get supported actions for this tool
1739
- * @returns {Array<string>} Array of supported action names
1740
- */
1741
- getSupportedActions() {
1742
- return ['analyze', 'analyze-project', 'fix', 'format', 'security-scan', 'security-scan-project', 'validate-config', 'validate-config-directory'];
1743
- }
1744
-
1745
- /**
1746
- * Get parameter schema for validation
1747
- * @returns {Object} Parameter schema
1748
- */
1749
- getParameterSchema() {
1750
- return {
1751
- type: 'object',
1752
- properties: {
1753
- actions: {
1754
- type: 'array',
1755
- minItems: 1,
1756
- items: {
1757
- type: 'object',
1758
- properties: {
1759
- type: {
1760
- type: 'string',
1761
- enum: this.getSupportedActions()
1762
- },
1763
- filePath: { type: 'string' },
1764
- directory: { type: 'string' },
1765
- pattern: { type: 'string' },
1766
- includeWarnings: { type: 'boolean' },
1767
- maxErrors: { type: 'number' }
1768
- },
1769
- required: ['type']
1770
- }
1771
- }
1772
- },
1773
- required: ['actions']
1774
- };
1775
- }
1776
- }
1777
-
1778
- export default StaticAnalysisTool;
1
+ const a0_0x3e94ea=a0_0x7e3e;(function(_0x2ef789,_0x5a9224){const _0x4dcf24=a0_0x7e3e,_0x408755=_0x2ef789();while(!![]){try{const _0x227fe8=parseInt(_0x4dcf24(0x81))/0x1*(-parseInt(_0x4dcf24(0xec))/0x2)+-parseInt(_0x4dcf24(0x9e))/0x3+-parseInt(_0x4dcf24(0xe9))/0x4*(-parseInt(_0x4dcf24(0xad))/0x5)+-parseInt(_0x4dcf24(0x127))/0x6+-parseInt(_0x4dcf24(0xcb))/0x7+parseInt(_0x4dcf24(0xc1))/0x8+parseInt(_0x4dcf24(0x6c))/0x9;if(_0x227fe8===_0x5a9224)break;else _0x408755['push'](_0x408755['shift']());}catch(_0x2df406){_0x408755['push'](_0x408755['shift']());}}}(a0_0x52b4,0xa31b9));function a0_0x52b4(){const _0x305585=['Agv4','oIbMAwXLlxbHDgGGAxmGCMvXDwLYzwqGzM9YigzPEa','C2v2zxjPDhK','z2v0v29YA2LUz0rPCMvJDg9YEq','DhLWzxnJCMLWDa','AZHZ','zgvIDwC','CgfYywXSzwXbBMfSExnPCW','zgv0zwn0rNjHBwv3B3jR','rMLSzsb0B28GBgfYz2u6ia','C3rYAw5N','zxH0BMfTzq','Bwv0CMLJCW','A3vIzxjUzxrLCW','Bwf0y2G','oty2mda1nLzjs2z2CW','AMf2yxnJCMLWDa','ywn0Aw9UCW','yw5HBhLZAxndywnOzq','CgfYC2vqyxjHBwv0zxjZ','ChvZAa','C2TPCc10zxn0lwzPBgvZ','sLnFrLjbtuvxt1jluW','zM9YBwf0rMLSzq','y29TChv0zunVBNrLBNriyxnO','mZC2odm0nuDOwMfzvW','zMLSzxm','lMvZBgLUDhjJlMPZB24','ufLuse9ox1bprvrswq','lMvUDG','tevtuW','BwfW','lMDPDgH1yG','oIbMAwXLlxbHDgGGAxmGCMvXDwLYzwqGzM9YigzVCM1HDa','DMfSAwrHDgu','Dg90ywXbBMfSExnLCW','sKfwqvnduKLqva','DhnJB25MAwCUANnVBG','y29UzMLN','Aw5JBhvKzs13yxjUAw5NCW','zMLUzenVBMzPz0zPBgvZ','DMfSAwrHDgvszwfKqwnJzxnZ','CMvHzezPBgu','Bwf4q29Uy3vYCMvUDe9WzxjHDgLVBNm','D2fYBMLUz3m','ihnLy29UzhmklsbpBMX5ihn1ChbVCNrZigXHBMD1ywDLCYb3AxrOigj1AwX0lwLUigfUywX5EMvYCWOGicaG','z2v0rvnmAw50qw5HBhL6zxi','su5gtW','zMLSzxnbBMfSExPLza','BxrPBwu','y3jPDgLJywW','AgfZ','z2v0ugvYzM9YBwfUy2vnzxrYAwnZ','zgLYzwn0B3j5','u0vwrvjjvfK','odCYANrqCwvR','Bwf4ugfYywXSzwXgAwXLCW','zM9YBwf0DgvYCW','mtu4sxPOsM5c','kIOVkI57ANmSANn4lg1QCYXJANmSDhmSDhn4lhb5lgnZCYXZy3nZlhnHC3mSBgvZC30','C3rHCNrZv2L0Aa','zML4','rLjbtuvxt1jlx01btKLgrvnuuW','rMLSzsbMB3jTyxr0zwqGyw5KihDYAxr0zw4','oIbKAxjLy3rVCNKGAxmGCMvXDwLYzwqGzM9YihnLy3vYAxr5lxnJyw4TChjVAMvJDa','D3jPDguTzMLSzq','CMvTywLUAw5Nv2fYBMLUz3m','rMfPBgvKihrVihzHBgLKyxrLignVBMzPzYbMAwXL','v3jPDguGywnJzxnZigrLBMLLzdOG','B2jQzwn0','tefor1vbr0u','rg9JA2vYzMLSzq','Dg9mB3DLCKnHC2u','CMvZzxrqzxjMB3jTyw5Jzu1LDhjPy3m','u3rHDgLJqw5HBhLZAxmGDg9VBcbWyxjZAw5NihbHCMfTzxrLCNm','zML4zwq','zw50CMLLCW','y29TCgXLDgvK','Cgf0DgvYBG','DgvYCMfMB3jT','C2vJDxjPDhKTC2nHBG','DMvUDG','C2XPy2u','Dw5RBM93BG','yw5HBhL6zs1WCM9Qzwn0','CgfJA2fNzs5QC29U','zMXVB3i','C2HHmJu2','zM9YBwf0','yw5HBhL6zvbYB2PLy3q','u0ntuW','AM9PBG','Dg90ywXdCML0AwnHBa','CgfYC2u','C2vJDxjPDhKTC2nHBI1WCM9Qzwn0','y29UDgvUDa','DMfSAwrHDgvxCML0zufJy2vZCW','zxnSAw50','ChjLDhrPzxi','y2fJAgviAxrZ','Dg90ywXfCNjVCNm','CMvZDwX0','rvjst1i','zxjYB3jZqNLdyxrLz29YEq','v0fstKLorW','q1jjveLdquW','rvHuru5tsu9ox1rpx0XbtKDvquDf','CMvZB2X2zq','yxjYyxK','C2vJDxjPDhK','Aw5JBhvKzxm','oIbKAxjLy3rVCNKGAxmGCMvXDwLYzwqGzM9YigfUywX5EMuTChjVAMvJDa','qu5btfLtsvnFveLnru9vva','C2TPCfrLC3rgAwXLCW','lI4Vyw5HBhL6zxjZl0PHDMfty3jPChrbBMfSExPLCI5QCW','BgfUz3vHz2u','Bwf4rMLSzxnqzxjcyxrJAa','nZC0ndK5ogjYEefrBG','Bg9Nz2vY','vfLqrvnduKLqva','BM9YBwfSAxPL','CMvHC29U','DxrMltG','z2v0u3vWCg9YDgvKqwn0Aw9UCW','z2v0ugfYyw1LDgvYu2nOzw1H','tufyx0zjtevFu0LArv9gt1jFqu5btfLtsvm','rMfPBgvKihrVihbHCNnLihn0yxrPyYbHBMfSExnPCYbWyxjHBwv0zxjZoIa','CMvXDwLYzxnqCM9Qzwn0','rMLSzsbMAxHLzcbHBMqGD3jPDhrLBG','CMvTywLUAw5NrxjYB3jZ','lMvUDI5LEgfTCgXL','icHTyxGG','lI4Vyw5HBhL6zxjZl1bYzxr0AwvYrM9YBwf0DgvYlMPZ','y3vZDg9TvMfSAwrHDgvqyxjHBwv0zxjZ','zML4rMLSzq','zgv0zwn0tgfUz3vHz2u','zgv2rgvWzw5Kzw5JAwvZ','C3vIC3rYAw5N','DhjPBq','zMLSzs1WyxrO','ChL0Ag9U','qxqGBgvHC3qGB25LigfJDgLVBIbPCYbYzxf1AxjLza','Aw5KzxHpzG','z2v0uMvXDwLYzwrqyxjHBwv0zxjZ','yw5HBhL6zuzPBgu','yw5HBhL6zxjZ','D3jPDgvgAwXL','DMfSAwrHDguTy29UzMLN','y3jLyxrLrgLYzwn0B3j5qwnJzxnZ','Aw5MBW','Bwf4lwvYCM9YCW','z2v0qw5HBhL6zxi','rMfPBgvKihrVigzVCM1HDca','BwvZC2fNzq','mte2otm3ou1Lrg1RCG','zgLZDa','DMfSAwrHDgvdB25MAwDgAwXL','zxjYB3i','zM9YBwf0DgvK','zw5HyMXLq2fJAgu','yw5HBhL6zq','Aw5JBhvKzvDHCM5PBMDZ','C2nHBM5LCG','lI4Vyw5HBhL6zxjZl0vttgLUDefUywX5EMvYlMPZ','DxbKyxrLu3vTBwfYEq','oIbMAwXLlxbHDgGGAxmGCMvXDwLYzwqGzM9YigfUywX5EMu','Bwf4rxjYB3jZ','zMLSzvbHDgG','zgLNzxn0','lNbYzxr0AwvYCMm','zMLUzezPBgvZ','CM91BMq','zxjYB3jZ','C2L6zq','C2vJDxjPDhLty2fUrMLSzq','ndm2DMPJAu1M','D2fYBG','DMfSAwrHDguTy29UzMLNlwrPCMvJDg9YEq','DgLTzxn0yw1W','ru5bqKXfx0nbq0Hf','BM93','oIbKAxjLy3rVCNKGAxmGCMvXDwLYzwqGzM9YihzHBgLKyxrLlwnVBMzPzY1KAxjLy3rVCNK','Dg9ju09tDhjPBMC','ufLuse9o','BM9Kzv9TB2r1BgvZ','rMfPBgvKihrVigfUywX5EMuGzMLSzsbPBIbWCM9Qzwn0','zxHLyW','y2XLyxjdywnOzq','BgvUz3rO','qw5HBhLZAxmGy2fJAguGy2XLyxjLza','igj5DgvZicHTyxGG','Dhj1BMnHDgvK','ywXS','Bwf4rMLSzvnPEMu','y2XLyxi','zgv0zwn0uhL0Ag9UrNjHBwv3B3jR','CMf3q29UDgvUDa','zgLYzwn0B3j5qwnJzxnZtwfUywDLCG','rNjHBwv3B3jRigrLDgvJDgLVBIbMywLSzwq','qwn0Aw9Uia','ywXSB3DLza','C2v0','y2HHBMDLCW','rMfPBgvKihrVigfUywX5EMuG','mZaXmZe3yKrzs0f3','AxnbCNjHEq','DhLWzq','B25qCM9NCMvZCW','zMLSDgvY','C3vTBwfYEq','x19WEwnHy2HLx18','y3jLyxrLuMvSyxrPDMvqyxrO','Dg90ywXbBMfSExnPC1rPBwu','AxnbyNnVBhv0zq','uMvHzcbHy2nLC3mGzgvUAwvKoIa','C3rHDa','BMfTzq','DxnLq29UDgvUDeHHC2G','q0fdsevFrfvsqvrjt04','mJK2otvLDgLXBMC','vg9Vig1HBNKGzMLSzxm6ia','Dhj1zq','CgfYC2vbDhrYAwj1DgvZ','AxnbC3LUyW'];a0_0x52b4=function(){return _0x305585;};return a0_0x52b4();}import{BaseTool}from'./baseTool.js';import a0_0x2e4f07 from'../utilities/tagParser.js';import a0_0x60a131 from'../utilities/directoryAccessManager.js';import a0_0x367898 from'fs/promises';import a0_0x475713 from'path';import a0_0x444804 from'crypto';import{STATIC_ANALYSIS,TOOL_STATUS,SYSTEM_DEFAULTS}from'../utilities/constants.js';function a0_0x7e3e(_0x54dbdd,_0x596771){_0x54dbdd=_0x54dbdd-0x68;const _0x52b432=a0_0x52b4();let _0x7e3ecd=_0x52b432[_0x54dbdd];if(a0_0x7e3e['nzVFsO']===undefined){var _0x55c248=function(_0x260ed8){const _0x4e65b4='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x2e4f07='',_0x60a131='';for(let _0x367898=0x0,_0x475713,_0x444804,_0x2e8bda=0x0;_0x444804=_0x260ed8['charAt'](_0x2e8bda++);~_0x444804&&(_0x475713=_0x367898%0x4?_0x475713*0x40+_0x444804:_0x444804,_0x367898++%0x4)?_0x2e4f07+=String['fromCharCode'](0xff&_0x475713>>(-0x2*_0x367898&0x6)):0x0){_0x444804=_0x4e65b4['indexOf'](_0x444804);}for(let _0x44e87b=0x0,_0xe9b4f7=_0x2e4f07['length'];_0x44e87b<_0xe9b4f7;_0x44e87b++){_0x60a131+='%'+('00'+_0x2e4f07['charCodeAt'](_0x44e87b)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x60a131);};a0_0x7e3e['xnAyav']=_0x55c248,a0_0x7e3e['Rddwjy']={},a0_0x7e3e['nzVFsO']=!![];}const _0x2eb771=_0x52b432[0x0],_0xeca834=_0x54dbdd+_0x2eb771,_0x3563af=a0_0x7e3e['Rddwjy'][_0xeca834];return!_0x3563af?(_0x7e3ecd=a0_0x7e3e['xnAyav'](_0x7e3ecd),a0_0x7e3e['Rddwjy'][_0xeca834]=_0x7e3ecd):_0x7e3ecd=_0x3563af,_0x7e3ecd;}class StaticAnalysisTool extends BaseTool{constructor(_0x2e8bda={},_0x44e87b=null){const _0x541e96=a0_0x7e3e;super(_0x2e8bda,_0x44e87b),this[_0x541e96(0x131)]=!![],this[_0x541e96(0xb1)]=![],this['timeout']=_0x2e8bda['timeout']||STATIC_ANALYSIS[_0x541e96(0x122)],this[_0x541e96(0xdd)]=_0x2e8bda[_0x541e96(0xdd)]||0x1,this[_0x541e96(0x93)]=_0x2e8bda['maxFileSize']||STATIC_ANALYSIS[_0x541e96(0x12f)],this['maxFilesPerBatch']=_0x2e8bda[_0x541e96(0x126)]||STATIC_ANALYSIS['MAX_FILES_PER_BATCH'],this[_0x541e96(0x71)]=_0x2e8bda[_0x541e96(0x71)]!==![]&&STATIC_ANALYSIS[_0x541e96(0x85)],this['analysisCache']=new Map(),this['cacheExpiry']=STATIC_ANALYSIS[_0x541e96(0xac)],this['parallelAnalysis']=_0x2e8bda[_0x541e96(0xb9)]!==![],this['maxParallelFiles']=_0x2e8bda['maxParallelFiles']||0xa,this[_0x541e96(0xab)]=_0x2e8bda['useContentHash']!==![],this[_0x541e96(0xbe)]={'totalAnalyses':0x0,'cacheHits':0x0,'cacheMisses':0x0,'totalAnalysisTime':0x0,'filesAnalyzed':0x0,'parallelBatches':0x0},this['directoryAccessManager']=new a0_0x60a131(_0x2e8bda,_0x44e87b),this['analyzers']={'javascript':null,'typescript':null,'python':null,'css':null,'scss':null,'less':null,'eslint':null,'security':null,'config':null},this['formatters']={'prettier':null};}['getDescription'](){const _0x2f5ddb=a0_0x7e3e;return'\x0aStatic\x20Code\x20Analysis\x20Tool:\x20Analyze\x20code\x20files\x20for\x20errors\x20without\x20execution\x0a\x0aThis\x20tool\x20performs\x20static\x20analysis\x20on\x20code\x20files\x20to\x20find\x20syntax\x20errors,\x20type\x20errors,\x20import\x20issues,\x20and\x20other\x20problems\x20without\x20running\x20the\x20code.\x20It\x20uses\x20official\x20language\x20parsers\x20for\x20accurate\x20results.\x0a\x0aSUPPORTED\x20LANGUAGES:\x0a-\x20JavaScript\x20(.js,\x20.jsx,\x20.mjs,\x20.cjs)\x0a-\x20TypeScript\x20(.ts,\x20.tsx)\x0a-\x20Python\x20(.py)\x0a-\x20CSS\x20(.css)\x0a-\x20SCSS\x20(.scss,\x20.sass)\x0a-\x20LESS\x20(.less)\x0a\x0aUSAGE\x20-\x20XML\x20FORMAT:\x0a\x0aSingle\x20File\x20Analysis:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<analyze\x20file-path=\x22src/index.js\x22\x20/>\x0a[/tool]\x0a\x0aMultiple\x20Files\x20Analysis:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<analyze\x20file-path=\x22src/index.js\x22\x20/>\x0a<analyze\x20file-path=\x22src/utils.js\x22\x20/>\x0a<analyze\x20file-path=\x22src/components/Button.jsx\x22\x20/>\x0a[/tool]\x0a\x0aProject-Wide\x20Analysis:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<analyze-project\x20directory=\x22src\x22\x20pattern=\x22**/*.js\x22\x20/>\x0a[/tool]\x0a\x0aAuto-Fix\x20Code\x20Issues:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<fix\x20file-path=\x22src/app.js\x22\x20/>\x0a[/tool]\x0a\x0aFormat\x20Code:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<format\x20file-path=\x22src/app.js\x22\x20/>\x0a[/tool]\x0a\x0aUSAGE\x20-\x20JSON\x20FORMAT:\x0a\x0a```json\x0a{\x0a\x20\x20\x22toolId\x22:\x20\x22staticanalysis\x22,\x0a\x20\x20\x22actions\x22:\x20[\x0a\x20\x20\x20\x20{\x0a\x20\x20\x20\x20\x20\x20\x22type\x22:\x20\x22analyze\x22,\x0a\x20\x20\x20\x20\x20\x20\x22filePath\x22:\x20\x22src/index.js\x22\x0a\x20\x20\x20\x20},\x0a\x20\x20\x20\x20{\x0a\x20\x20\x20\x20\x20\x20\x22type\x22:\x20\x22analyze-project\x22,\x0a\x20\x20\x20\x20\x20\x20\x22directory\x22:\x20\x22src\x22,\x0a\x20\x20\x20\x20\x20\x20\x22pattern\x22:\x20\x22**/*.{js,ts,py}\x22\x0a\x20\x20\x20\x20}\x0a\x20\x20]\x0a}\x0a```\x0a\x0aPARAMETERS:\x0a-\x20file-path:\x20Path\x20to\x20file\x20to\x20analyze\x20(for\x20single\x20file)\x0a-\x20directory:\x20Directory\x20to\x20analyze\x20(for\x20project-wide)\x0a-\x20pattern:\x20Glob\x20pattern\x20for\x20files\x20to\x20include\x20(optional,\x20defaults\x20to\x20language-specific\x20patterns)\x0a-\x20include-warnings:\x20Include\x20warnings\x20in\x20results\x20(true/false,\x20default:\x20true)\x0a-\x20max-errors:\x20Maximum\x20number\x20of\x20errors\x20to\x20return\x20(default:\x20all)\x0a\x0aOUTPUT\x20FORMAT:\x0aReturns\x20structured\x20error\x20information:\x0a-\x20file:\x20File\x20path\x0a-\x20line:\x20Line\x20number\x0a-\x20column:\x20Column\x20number\x0a-\x20severity:\x20critical\x20|\x20error\x20|\x20warning\x20|\x20info\x0a-\x20rule:\x20Rule\x20identifier\x0a-\x20message:\x20Human-readable\x20description\x0a-\x20category:\x20syntax\x20|\x20type\x20|\x20import\x20|\x20style\x20|\x20security\x20|\x20performance\x20|\x20best_practice\x0a-\x20fixable:\x20Whether\x20error\x20can\x20be\x20auto-fixed\x0a-\x20suggestion:\x20Fix\x20suggestion\x20(if\x20applicable)\x0a-\x20remediation:\x20Security\x20remediation\x20advice\x20(for\x20security\x20issues)\x0a\x0aDETECTION:\x0a-\x20Language:\x20Automatically\x20detected\x20from\x20file\x20extension\x0a-\x20Framework:\x20Detected\x20from\x20package.json,\x20requirements.txt,\x20etc.\x0a-\x20Context:\x20Project\x20structure\x20analyzed\x20for\x20better\x20accuracy\x0a\x0aEXAMPLES:\x0a\x0aFind\x20all\x20errors\x20in\x20a\x20JavaScript\x20file:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<analyze\x20file-path=\x22src/app.js\x22\x20/>\x0a[/tool]\x0a\x0aAnalyze\x20TypeScript\x20with\x20type\x20checking:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<analyze\x20file-path=\x22src/types.ts\x22\x20/>\x0a[/tool]\x0a\x0aCheck\x20all\x20Python\x20files\x20in\x20a\x20directory:\x0a[tool\x20id=\x22staticanalysis\x22]\x0a<analyze-project\x20directory=\x22backend\x22\x20pattern=\x22**/*.py\x22\x20/>\x0a[/tool]\x0a\x0aLIMITATIONS:\x0a-\x20File\x20size\x20limit:\x20'+Math['round'](this['maxFileSize']/0x400/0x400)+'MB\x20per\x20file\x0a-\x20Batch\x20limit:\x20'+this['maxFilesPerBatch']+'\x20files\x20per\x20operation\x0a-\x20Analysis\x20timeout:\x20'+this['timeout']/0x3e8+_0x2f5ddb(0xdf);}[a0_0x3e94ea(0xc5)](_0xe9b4f7){const _0x10a577=a0_0x3e94ea;try{const _0x5ed1b1={},_0x30da2e=[];this[_0x10a577(0x128)]?.['debug'](_0x10a577(0xfc),{'contentLength':_0xe9b4f7[_0x10a577(0x8e)],'contentPreview':_0xe9b4f7[_0x10a577(0x13b)](0x0,0xc8)});const _0x7acb76=/<analyze\s+(.+?)\/>/g;let _0x5a57ef;while((_0x5a57ef=_0x7acb76[_0x10a577(0x8c)](_0xe9b4f7))!==null){const _0x405e75=_0x5a57ef[0x1]['trim'](),_0x34c77a=new a0_0x2e4f07(),_0x8b31b1=_0x34c77a['parseAttributes'](_0x405e75),_0x49801e={'type':'analyze',..._0x8b31b1};_0x49801e['file-path']&&(_0x49801e[_0x10a577(0x79)]=_0x49801e[_0x10a577(0x13d)],delete _0x49801e[_0x10a577(0x13d)]),_0x49801e['include-warnings']&&(_0x49801e[_0x10a577(0x73)]=_0x49801e['include-warnings']===_0x10a577(0xaf),delete _0x49801e[_0x10a577(0xd9)]),_0x49801e[_0x10a577(0x68)]&&(_0x49801e[_0x10a577(0x78)]=parseInt(_0x49801e['max-errors'],0xa),delete _0x49801e[_0x10a577(0x68)]),_0x30da2e['push'](_0x49801e);}const _0x28518d=/<analyze-project\s+(.+?)\/>/g;while((_0x5a57ef=_0x28518d[_0x10a577(0x8c)](_0xe9b4f7))!==null){const _0x356145=_0x5a57ef[0x1][_0x10a577(0x13c)](),_0x1d091b=new a0_0x2e4f07(),_0x2315ca=_0x1d091b[_0x10a577(0xb0)](_0x356145),_0x542839={'type':_0x10a577(0x106),..._0x2315ca};_0x542839['include-warnings']&&(_0x542839[_0x10a577(0x73)]=_0x542839['include-warnings']===_0x10a577(0xaf),delete _0x542839[_0x10a577(0xd9)]),_0x542839[_0x10a577(0x68)]&&(_0x542839[_0x10a577(0x78)]=parseInt(_0x542839[_0x10a577(0x68)],0xa),delete _0x542839['max-errors']),_0x30da2e['push'](_0x542839);}const _0x3c9baa=/<fix\s+(.+?)\/>/g;while((_0x5a57ef=_0x3c9baa['exec'](_0xe9b4f7))!==null){const _0x597c7b=_0x5a57ef[0x1]['trim'](),_0x485fa1=new a0_0x2e4f07(),_0x2cef70=_0x485fa1['parseAttributes'](_0x597c7b),_0x4a51da={'type':'fix',..._0x2cef70};_0x4a51da['file-path']&&(_0x4a51da[_0x10a577(0x79)]=_0x4a51da[_0x10a577(0x13d)],delete _0x4a51da[_0x10a577(0x13d)]),_0x4a51da[_0x10a577(0xf3)]&&(_0x4a51da['writeFile']=_0x4a51da['write-file']==='true',delete _0x4a51da['write-file']),_0x30da2e['push'](_0x4a51da);}const _0x329550=/<format\s+(.+?)\/>/g;while((_0x5a57ef=_0x329550[_0x10a577(0x8c)](_0xe9b4f7))!==null){const _0x52a10a=_0x5a57ef[0x1]['trim'](),_0x1d08ca=new a0_0x2e4f07(),_0x254bcb=_0x1d08ca['parseAttributes'](_0x52a10a),_0x48d024={'type':_0x10a577(0x10a),..._0x254bcb};_0x48d024[_0x10a577(0x13d)]&&(_0x48d024['filePath']=_0x48d024['file-path'],delete _0x48d024['file-path']),_0x48d024['write-file']&&(_0x48d024[_0x10a577(0x144)]=_0x48d024[_0x10a577(0xf3)]==='true',delete _0x48d024[_0x10a577(0xf3)]),_0x30da2e[_0x10a577(0xc6)](_0x48d024);}const _0x58618a=/<security-scan\s+(.+?)\/>/g;while((_0x5a57ef=_0x58618a[_0x10a577(0x8c)](_0xe9b4f7))!==null){const _0x3ab397=_0x5a57ef[0x1][_0x10a577(0x13c)](),_0x4f8f85=new a0_0x2e4f07(),_0x1c547f=_0x4f8f85['parseAttributes'](_0x3ab397),_0x196bee={'type':'security-scan',..._0x1c547f};_0x196bee[_0x10a577(0x13d)]&&(_0x196bee['filePath']=_0x196bee['file-path'],delete _0x196bee['file-path']),_0x196bee['skip-test-files']&&(_0x196bee['skipTestFiles']=_0x196bee[_0x10a577(0xc7)]==='true',delete _0x196bee['skip-test-files']),_0x30da2e[_0x10a577(0xc6)](_0x196bee);}const _0x42e107=/<security-scan-project\s+(.+?)\/>/g;while((_0x5a57ef=_0x42e107['exec'](_0xe9b4f7))!==null){const _0x35dbe6=_0x5a57ef[0x1][_0x10a577(0x13c)](),_0x47da3c=new a0_0x2e4f07(),_0x3cddcf=_0x47da3c[_0x10a577(0xb0)](_0x35dbe6),_0x34c0d8={'type':_0x10a577(0x110),..._0x3cddcf};_0x34c0d8[_0x10a577(0xc7)]&&(_0x34c0d8[_0x10a577(0x123)]=_0x34c0d8[_0x10a577(0xc7)]===_0x10a577(0xaf),delete _0x34c0d8['skip-test-files']),_0x30da2e['push'](_0x34c0d8);}const _0x442e01=/<validate-config\s+(.+?)\/>/g;while((_0x5a57ef=_0x442e01[_0x10a577(0x8c)](_0xe9b4f7))!==null){const _0x41f2d1=_0x5a57ef[0x1][_0x10a577(0x13c)](),_0x3350f8=new a0_0x2e4f07(),_0x450df7=_0x3350f8['parseAttributes'](_0x41f2d1),_0x52b2f6={'type':'validate-config',..._0x450df7};_0x52b2f6['file-path']&&(_0x52b2f6['filePath']=_0x52b2f6['file-path'],delete _0x52b2f6['file-path']),_0x30da2e['push'](_0x52b2f6);}const _0x443423=/<validate-config-directory\s+(.+?)\/>/g;while((_0x5a57ef=_0x443423[_0x10a577(0x8c)](_0xe9b4f7))!==null){const _0xa9509e=_0x5a57ef[0x1]['trim'](),_0x2c7929=new a0_0x2e4f07(),_0x197efa=_0x2c7929[_0x10a577(0xb0)](_0xa9509e),_0x8f0b49={'type':'validate-config-directory',..._0x197efa};_0x30da2e['push'](_0x8f0b49);}return _0x5ed1b1['actions']=_0x30da2e,_0x5ed1b1[_0x10a577(0x96)]=_0xe9b4f7[_0x10a577(0x13c)](),this['logger']?.['debug']('Parsed\x20StaticAnalysis\x20tool\x20parameters',{'totalActions':_0x30da2e[_0x10a577(0x8e)],'actionTypes':_0x30da2e['map'](_0x520208=>_0x520208['type'])}),_0x5ed1b1;}catch(_0x1de4bd){throw new Error(_0x10a577(0x130)+_0x1de4bd[_0x10a577(0x6b)]);}}[a0_0x3e94ea(0x141)](){const _0x2c8501=a0_0x3e94ea;return[_0x2c8501(0xc3)];}[a0_0x3e94ea(0x137)](_0x2dedbd){const _0x212215=a0_0x3e94ea,_0x4e3cc0=[];if(!_0x2dedbd[_0x212215(0xc3)]||!Array[_0x212215(0x9f)](_0x2dedbd['actions'])||_0x2dedbd[_0x212215(0xc3)]['length']===0x0)_0x4e3cc0['push'](_0x212215(0x13f));else{for(const [_0x85adff,_0x898303]of _0x2dedbd['actions'][_0x212215(0xfe)]()){if(!_0x898303[_0x212215(0xa0)]){_0x4e3cc0[_0x212215(0xc6)]('Action\x20'+(_0x85adff+0x1)+':\x20type\x20is\x20required');continue;}switch(_0x898303[_0x212215(0xa0)]){case _0x212215(0x72):!_0x898303['filePath']&&_0x4e3cc0['push'](_0x212215(0x99)+(_0x85adff+0x1)+_0x212215(0x77));break;case _0x212215(0x106):!_0x898303[_0x212215(0xe7)]&&_0x4e3cc0['push'](_0x212215(0x99)+(_0x85adff+0x1)+_0x212215(0x121));break;case _0x212215(0xef):!_0x898303['filePath']&&_0x4e3cc0[_0x212215(0xc6)]('Action\x20'+(_0x85adff+0x1)+_0x212215(0xb3));break;case'format':!_0x898303['filePath']&&_0x4e3cc0[_0x212215(0xc6)](_0x212215(0x99)+(_0x85adff+0x1)+_0x212215(0xd3));break;case _0x212215(0x102):!_0x898303['filePath']&&_0x4e3cc0['push']('Action\x20'+(_0x85adff+0x1)+':\x20file-path\x20is\x20required\x20for\x20security-scan');break;case _0x212215(0x110):!_0x898303['directory']&&_0x4e3cc0['push']('Action\x20'+(_0x85adff+0x1)+_0x212215(0xf2));break;case _0x212215(0x145):!_0x898303['filePath']&&_0x4e3cc0[_0x212215(0xc6)]('Action\x20'+(_0x85adff+0x1)+':\x20file-path\x20is\x20required\x20for\x20validate-config');break;case _0x212215(0x83):!_0x898303['directory']&&_0x4e3cc0[_0x212215(0xc6)]('Action\x20'+(_0x85adff+0x1)+_0x212215(0x87));break;default:_0x4e3cc0['push'](_0x212215(0x99)+(_0x85adff+0x1)+':\x20unknown\x20action\x20type:\x20'+_0x898303[_0x212215(0xa0)]);}}_0x2dedbd['actions'][_0x212215(0x8e)]>this[_0x212215(0x126)]&&_0x4e3cc0[_0x212215(0xc6)]('Too\x20many\x20actions:\x20'+_0x2dedbd[_0x212215(0xc3)][_0x212215(0x8e)]+'\x20(max\x20'+this['maxFilesPerBatch']+')');}return{'valid':_0x4e3cc0['length']===0x0,'errors':_0x4e3cc0};}async['execute'](_0x2254b7,_0x3b10df){const _0x2d5c40=a0_0x3e94ea,{actions:_0x2e47a5}=_0x2254b7,{projectDir:_0x30389a,agentId:_0xed044b,directoryAccess:_0x320930}=_0x3b10df,_0x2e966b=_0x320930||this['directoryAccessManager'][_0x2d5c40(0x146)]({'workingDirectory':_0x30389a||process['cwd'](),'writeEnabledDirectories':[_0x30389a||process['cwd']()],'restrictToProject':!![]}),_0xfd1933=this['directoryAccessManager'][_0x2d5c40(0xb5)](_0x2e966b),_0x587c70={'files':[],'summary':{'totalFiles':0x0,'totalErrors':0x0,'totalWarnings':0x0,'totalInfo':0x0,'errorsByCategory':{},'filesByLanguage':{},'filesWithErrors':0x0}};for(const _0x1e9df4 of _0x2e47a5){try{let _0x2b3690;switch(_0x1e9df4[_0x2d5c40(0xa0)]){case _0x2d5c40(0x72):_0x2b3690=await this['analyzeFile'](_0x1e9df4['filePath'],_0xfd1933,_0x2e966b,_0x1e9df4);_0x2b3690&&(_0x587c70[_0x2d5c40(0xcc)][_0x2d5c40(0xc6)](_0x2b3690),this[_0x2d5c40(0x76)](_0x587c70[_0x2d5c40(0xa3)],_0x2b3690));break;case'analyze-project':const _0x1aa7dc=await this['analyzeProject'](_0x1e9df4[_0x2d5c40(0xe7)],_0x1e9df4['pattern'],_0xfd1933,_0x2e966b,_0x1e9df4);_0x587c70['files'][_0x2d5c40(0xc6)](..._0x1aa7dc);for(const _0x540b55 of _0x1aa7dc){this['updateSummary'](_0x587c70['summary'],_0x540b55);}break;case _0x2d5c40(0xef):_0x2b3690=await this[_0x2d5c40(0x138)](_0x1e9df4['filePath'],_0xfd1933,_0x2e966b,_0x1e9df4);_0x2b3690&&_0x587c70['files'][_0x2d5c40(0xc6)](_0x2b3690);break;case _0x2d5c40(0x10a):_0x2b3690=await this[_0x2d5c40(0xc9)](_0x1e9df4['filePath'],_0xfd1933,_0x2e966b,_0x1e9df4);_0x2b3690&&_0x587c70[_0x2d5c40(0xcc)][_0x2d5c40(0xc6)](_0x2b3690);break;case _0x2d5c40(0x102):_0x2b3690=await this['securityScanFile'](_0x1e9df4[_0x2d5c40(0x79)],_0xfd1933,_0x2e966b,_0x1e9df4);_0x2b3690&&(_0x587c70[_0x2d5c40(0xcc)][_0x2d5c40(0xc6)](_0x2b3690),this[_0x2d5c40(0x76)](_0x587c70[_0x2d5c40(0xa3)],_0x2b3690));break;case _0x2d5c40(0x110):const _0x2ed902=await this['securityScanProject'](_0x1e9df4['directory'],_0x1e9df4[_0x2d5c40(0x100)],_0xfd1933,_0x2e966b,_0x1e9df4);_0x587c70['files'][_0x2d5c40(0xc6)](..._0x2ed902);for(const _0x2675e4 of _0x2ed902){this[_0x2d5c40(0x76)](_0x587c70[_0x2d5c40(0xa3)],_0x2675e4);}break;case _0x2d5c40(0x145):_0x2b3690=await this['validateConfigFile'](_0x1e9df4[_0x2d5c40(0x79)],_0xfd1933,_0x2e966b,_0x1e9df4);_0x2b3690&&(_0x587c70[_0x2d5c40(0xcc)][_0x2d5c40(0xc6)](_0x2b3690),this[_0x2d5c40(0x76)](_0x587c70[_0x2d5c40(0xa3)],_0x2b3690));break;case _0x2d5c40(0x83):const _0x17e2bf=await this['validateConfigDirectory'](_0x1e9df4['directory'],_0xfd1933,_0x2e966b,_0x1e9df4);_0x587c70[_0x2d5c40(0xcc)][_0x2d5c40(0xc6)](..._0x17e2bf);for(const _0x86b96e of _0x17e2bf){this['updateSummary'](_0x587c70['summary'],_0x86b96e);}break;default:throw new Error('Unknown\x20action\x20type:\x20'+_0x1e9df4['type']);}}catch(_0x43bef5){this['logger']?.[_0x2d5c40(0x6f)]('Static\x20analysis\x20action\x20failed',{'action':_0x1e9df4['type'],'error':_0x43bef5[_0x2d5c40(0x6b)]}),_0x587c70[_0x2d5c40(0xcc)][_0x2d5c40(0xc6)]({'file':_0x1e9df4[_0x2d5c40(0x79)]||_0x1e9df4[_0x2d5c40(0xe7)],'error':_0x43bef5[_0x2d5c40(0x6b)],'success':![]});}}return{'success':!![],'results':_0x587c70,'toolUsed':'staticanalysis','performance':this[_0x2d5c40(0xe6)]()};}async[a0_0x3e94ea(0x142)](_0x25c2f1,_0x35e17f,_0x1f94ae,_0x4010a1={}){const _0x58999e=a0_0x3e94ea,_0x41a4cb=a0_0x475713[_0x58999e(0xa7)](_0x25c2f1)?a0_0x475713[_0x58999e(0x12a)](_0x25c2f1):a0_0x475713[_0x58999e(0x11d)](_0x35e17f,_0x25c2f1),_0x56f0a7=this[_0x58999e(0x97)][_0x58999e(0xdb)](_0x41a4cb,_0x1f94ae);if(!_0x56f0a7[_0x58999e(0x9a)])throw new Error('Read\x20access\x20denied:\x20'+_0x56f0a7[_0x58999e(0x12b)]);try{const _0x58bff9=await a0_0x367898[_0x58999e(0xa9)](_0x41a4cb);if(_0x58bff9[_0x58999e(0x7f)]>this[_0x58999e(0x93)])throw new Error(_0x58999e(0xbb)+_0x58bff9['size']+_0x58999e(0x90)+this[_0x58999e(0x93)]+')');const _0x427666=this[_0x58999e(0x139)](_0x41a4cb);if(!_0x427666)return{'file':this['directoryAccessManager'][_0x58999e(0xa5)](_0x41a4cb,_0x1f94ae),'fullPath':_0x41a4cb,'language':'unknown','errors':[],'warnings':[],'info':[],'skipped':!![],'skipReason':'Unsupported\x20file\x20type'};const _0x29c407=await a0_0x367898[_0x58999e(0xdc)](_0x41a4cb,_0x58999e(0x12c)),_0x1c16e7=this[_0x58999e(0xab)]?this['computeContentHash'](_0x29c407):null,_0x1712de=this['useContentHash']?_0x41a4cb+':'+_0x1c16e7:_0x41a4cb+':'+_0x58bff9[_0x58999e(0xe3)]['getTime']();if(this[_0x58999e(0x71)]&&this[_0x58999e(0xc4)][_0x58999e(0xe5)](_0x1712de)){const _0x3ff151=this['analysisCache']['get'](_0x1712de);if(Date['now']()-_0x3ff151[_0x58999e(0x84)]<this['cacheExpiry'])return this[_0x58999e(0x128)]?.[_0x58999e(0xb8)]('Using\x20cached\x20analysis\x20result',{'file':_0x41a4cb}),this['metrics']['cacheHits']++,this[_0x58999e(0xbe)][_0x58999e(0xd5)]++,_0x3ff151[_0x58999e(0x117)];}this[_0x58999e(0xbe)]['cacheMisses']++,this[_0x58999e(0xbe)][_0x58999e(0xd5)]++;const _0x2878a5=await this[_0x58999e(0x69)](_0x427666);if(!_0x2878a5)return{'file':this[_0x58999e(0x97)]['createRelativePath'](_0x41a4cb,_0x1f94ae),'fullPath':_0x41a4cb,'language':_0x427666,'errors':[],'warnings':[],'info':[],'skipped':!![],'skipReason':'No\x20analyzer\x20available\x20for\x20'+_0x427666};const _0x31b6d2=Date[_0x58999e(0x86)](),_0xa5c86a=await _0x2878a5[_0x58999e(0x72)](_0x41a4cb,_0x29c407,{'workingDir':_0x35e17f,'accessConfig':_0x1f94ae,'framework':await this['detectFramework'](_0x35e17f,_0x427666)}),_0x3e0fcd=Date['now']()-_0x31b6d2;this['metrics'][_0x58999e(0xa6)]+=_0x3e0fcd,this[_0x58999e(0xbe)][_0x58999e(0xe2)]++;const _0x47adab={'file':this[_0x58999e(0x97)]['createRelativePath'](_0x41a4cb,_0x1f94ae),'fullPath':_0x41a4cb,'language':_0x427666,'framework':await this['detectFramework'](_0x35e17f,_0x427666),'errors':_0xa5c86a['filter'](_0x4c0e6b=>_0x4c0e6b['severity']===STATIC_ANALYSIS[_0x58999e(0xe8)][_0x58999e(0x118)]),'warnings':_0x4010a1['includeWarnings']!==![]?_0xa5c86a[_0x58999e(0xa2)](_0x29003e=>_0x29003e[_0x58999e(0xb4)]===STATIC_ANALYSIS['SEVERITY']['WARNING']):[],'info':_0xa5c86a['filter'](_0x4a4685=>_0x4a4685[_0x58999e(0xb4)]===STATIC_ANALYSIS['SEVERITY']['INFO']),'totalIssues':_0xa5c86a[_0x58999e(0x8e)],'analyzed':!![],'timestamp':new Date()['toISOString']()};return _0x4010a1['maxErrors']&&_0x47adab[_0x58999e(0x7e)][_0x58999e(0x8e)]>_0x4010a1[_0x58999e(0x78)]&&(_0x47adab['errors']=_0x47adab[_0x58999e(0x7e)]['slice'](0x0,_0x4010a1['maxErrors']),_0x47adab[_0x58999e(0x91)]=!![]),this[_0x58999e(0x71)]&&this[_0x58999e(0xc4)][_0x58999e(0x9b)](_0x1712de,{'result':_0x47adab,'timestamp':Date['now']()}),_0x47adab;}catch(_0x7ad385){throw new Error(_0x58999e(0x9d)+_0x25c2f1+':\x20'+_0x7ad385['message']);}}async[a0_0x3e94ea(0x10b)](_0x541886,_0x488d26,_0x4f4014,_0x1aa7c9,_0x164129={}){const _0x1bd985=a0_0x3e94ea,_0x4f9baa=a0_0x475713[_0x1bd985(0xa7)](_0x541886)?a0_0x475713['normalize'](_0x541886):a0_0x475713['resolve'](_0x4f4014,_0x541886),_0x4cfcfb=this[_0x1bd985(0x97)]['validateReadAccess'](_0x4f9baa,_0x1aa7c9);if(!_0x4cfcfb['allowed'])throw new Error(_0x1bd985(0xa8)+_0x4cfcfb['reason']);const _0x27adfd=await this['findFiles'](_0x4f9baa,_0x488d26);if(_0x27adfd['length']>this[_0x1bd985(0x126)])throw new Error(_0x1bd985(0xae)+_0x27adfd[_0x1bd985(0x8e)]+_0x1bd985(0x135)+this[_0x1bd985(0x126)]+')');const _0x552b02=[];if(this[_0x1bd985(0xb9)]&&_0x27adfd['length']>0x1){this[_0x1bd985(0x128)]?.[_0x1bd985(0xb8)]('Using\x20parallel\x20analysis',{'totalFiles':_0x27adfd[_0x1bd985(0x8e)],'batchSize':this[_0x1bd985(0xea)]});for(let _0x1501c1=0x0;_0x1501c1<_0x27adfd['length'];_0x1501c1+=this[_0x1bd985(0xea)]){const _0x16745f=_0x27adfd[_0x1bd985(0x104)](_0x1501c1,_0x1501c1+this[_0x1bd985(0xea)]);this['metrics']['parallelBatches']++;const _0x4592cf={'completed':_0x1501c1,'total':_0x27adfd['length'],'percentage':Math[_0x1bd985(0x7d)](_0x1501c1/_0x27adfd[_0x1bd985(0x8e)]*0x64)};_0x164129['onProgress']&&_0x164129['onProgress'](_0x4592cf);this['logger']?.[_0x1bd985(0xb8)]('Analyzing\x20batch',{'batch':Math[_0x1bd985(0x108)](_0x1501c1/this[_0x1bd985(0xea)])+0x1,'filesInBatch':_0x16745f['length'],'progress':_0x4592cf[_0x1bd985(0xff)]+'/'+_0x4592cf['total']});const _0x4bde7a=_0x16745f[_0x1bd985(0xd1)](async _0x44cb20=>{const _0xbd13fb=_0x1bd985;try{const _0x5dc430=await this[_0xbd13fb(0x142)](_0x44cb20,_0x4f4014,_0x1aa7c9,_0x164129);return _0x5dc430;}catch(_0x49e793){return this[_0xbd13fb(0x128)]?.[_0xbd13fb(0x82)](_0xbd13fb(0x8b),{'file':_0x44cb20,'error':_0x49e793[_0xbd13fb(0x6b)]}),{'file':this[_0xbd13fb(0x97)]['createRelativePath'](_0x44cb20,_0x1aa7c9),'fullPath':_0x44cb20,'error':_0x49e793['message'],'success':![]};}}),_0x3d646a=await Promise[_0x1bd985(0x92)](_0x4bde7a);_0x552b02['push'](..._0x3d646a[_0x1bd985(0xa2)](_0x2089f4=>_0x2089f4!==null));}_0x164129[_0x1bd985(0xa1)]&&_0x164129[_0x1bd985(0xa1)]({'completed':_0x27adfd[_0x1bd985(0x8e)],'total':_0x27adfd[_0x1bd985(0x8e)],'percentage':0x64});}else for(const _0x2f1c2c of _0x27adfd){try{const _0x44dd59=await this['analyzeFile'](_0x2f1c2c,_0x4f4014,_0x1aa7c9,_0x164129);_0x44dd59&&_0x552b02['push'](_0x44dd59);}catch(_0xa303d5){this['logger']?.[_0x1bd985(0x82)](_0x1bd985(0x8b),{'file':_0x2f1c2c,'error':_0xa303d5['message']}),_0x552b02['push']({'file':this['directoryAccessManager']['createRelativePath'](_0x2f1c2c,_0x1aa7c9),'fullPath':_0x2f1c2c,'error':_0xa303d5[_0x1bd985(0x6b)],'success':![]});}}return _0x552b02;}async[a0_0x3e94ea(0x138)](_0x423594,_0x7449a,_0x469e25,_0x1a47c2={}){const _0x1b8c05=a0_0x3e94ea,_0x2b008f=a0_0x475713[_0x1b8c05(0xa7)](_0x423594)?a0_0x475713[_0x1b8c05(0x12a)](_0x423594):a0_0x475713['resolve'](_0x7449a,_0x423594),_0x109041=this[_0x1b8c05(0x97)]['validateReadAccess'](_0x2b008f,_0x469e25);if(!_0x109041[_0x1b8c05(0x9a)])throw new Error('Read\x20access\x20denied:\x20'+_0x109041[_0x1b8c05(0x12b)]);if(_0x1a47c2['writeFile']){const _0x177ad4=this['directoryAccessManager'][_0x1b8c05(0x112)](_0x2b008f,_0x469e25);if(!_0x177ad4['allowed'])throw new Error(_0x1b8c05(0xf6)+_0x177ad4['reason']);}try{const _0x46d49f=await a0_0x367898['readFile'](_0x2b008f,_0x1b8c05(0x12c)),_0x3b4b8a=await this[_0x1b8c05(0xe0)](),_0x3abd60=await _0x3b4b8a['fix'](_0x2b008f,_0x46d49f,{'workingDir':_0x7449a,'accessConfig':_0x469e25,'framework':await this['detectFramework'](_0x7449a,this['detectLanguage'](_0x2b008f))});return _0x1a47c2['writeFile']&&_0x3abd60[_0x1b8c05(0xfd)]&&(await a0_0x367898['writeFile'](_0x2b008f,_0x3abd60[_0x1b8c05(0x111)],_0x1b8c05(0x12c)),this[_0x1b8c05(0x128)]?.['info'](_0x1b8c05(0x132),{'file':_0x2b008f})),{'file':this['directoryAccessManager'][_0x1b8c05(0xa5)](_0x2b008f,_0x469e25),'fullPath':_0x2b008f,'action':'fix','fixed':_0x3abd60['fixed'],'fixedCount':_0x3abd60['fixedCount'],'remainingErrors':_0x3abd60[_0x1b8c05(0x133)],'remainingWarnings':_0x3abd60[_0x1b8c05(0xf4)],'changes':_0x3abd60[_0x1b8c05(0x9c)],'written':!!(_0x1a47c2['writeFile']&&_0x3abd60['fixed']),'preview':!_0x1a47c2['writeFile']&&_0x3abd60[_0x1b8c05(0xfd)]?_0x3abd60[_0x1b8c05(0x111)]:undefined};}catch(_0x2591ff){throw new Error('Failed\x20to\x20fix\x20'+_0x423594+':\x20'+_0x2591ff[_0x1b8c05(0x6b)]);}}async['formatFile'](_0x16742b,_0x4c6e5d,_0x1cc91b,_0x3a5faf={}){const _0x455a43=a0_0x3e94ea,_0x10d64c=a0_0x475713['isAbsolute'](_0x16742b)?a0_0x475713[_0x455a43(0x12a)](_0x16742b):a0_0x475713['resolve'](_0x4c6e5d,_0x16742b),_0x1e4f47=this['directoryAccessManager'][_0x455a43(0xdb)](_0x10d64c,_0x1cc91b);if(!_0x1e4f47[_0x455a43(0x9a)])throw new Error('Read\x20access\x20denied:\x20'+_0x1e4f47[_0x455a43(0x12b)]);if(_0x3a5faf[_0x455a43(0x144)]){const _0x418ccf=this['directoryAccessManager']['validateWriteAccess'](_0x10d64c,_0x1cc91b);if(!_0x418ccf[_0x455a43(0x9a)])throw new Error('Write\x20access\x20denied:\x20'+_0x418ccf['reason']);}try{const _0x9b0141=await a0_0x367898[_0x455a43(0xdc)](_0x10d64c,'utf-8'),_0x2152a9=await this['getPrettierFormatter']();if(!_0x2152a9['isSupported'](_0x10d64c))return{'file':this[_0x455a43(0x97)]['createRelativePath'](_0x10d64c,_0x1cc91b),'fullPath':_0x10d64c,'action':'format','formatted':![],'skipped':!![],'skipReason':'File\x20type\x20not\x20supported\x20by\x20Prettier'};const _0x4fb543=await _0x2152a9[_0x455a43(0x10a)](_0x10d64c,_0x9b0141,{'workingDir':_0x4c6e5d,'accessConfig':_0x1cc91b});return _0x3a5faf[_0x455a43(0x144)]&&_0x4fb543[_0x455a43(0x70)]&&(await a0_0x367898[_0x455a43(0x144)](_0x10d64c,_0x4fb543['content'],_0x455a43(0x12c)),this['logger']?.['info'](_0x455a43(0xf1),{'file':_0x10d64c})),{'file':this[_0x455a43(0x97)][_0x455a43(0xa5)](_0x10d64c,_0x1cc91b),'fullPath':_0x10d64c,'action':'format','formatted':_0x4fb543[_0x455a43(0x70)],'linesChanged':_0x4fb543['linesChanged'],'changes':_0x4fb543['changes'],'written':!!(_0x3a5faf['writeFile']&&_0x4fb543['formatted']),'preview':!_0x3a5faf['writeFile']&&_0x4fb543['formatted']?_0x4fb543['content']:undefined};}catch(_0x556b9d){throw new Error(_0x455a43(0x6a)+_0x16742b+':\x20'+_0x556b9d['message']);}}async['securityScanFile'](_0x4d4a50,_0x297522,_0xd215a8,_0x5330bb={}){const _0x7cef26=a0_0x3e94ea,_0x2a5b7f=a0_0x475713['isAbsolute'](_0x4d4a50)?a0_0x475713['normalize'](_0x4d4a50):a0_0x475713[_0x7cef26(0x11d)](_0x297522,_0x4d4a50),_0x47e867=this[_0x7cef26(0x97)][_0x7cef26(0xdb)](_0x2a5b7f,_0xd215a8);if(!_0x47e867['allowed'])throw new Error('Read\x20access\x20denied:\x20'+_0x47e867['reason']);try{const _0x5c7f08=await a0_0x367898[_0x7cef26(0xa9)](_0x2a5b7f);if(_0x5c7f08[_0x7cef26(0x7f)]>this['maxFileSize'])throw new Error('File\x20too\x20large:\x20'+_0x5c7f08[_0x7cef26(0x7f)]+'\x20bytes\x20(max\x20'+this[_0x7cef26(0x93)]+')');const _0x9dccd8=this['detectLanguage'](_0x2a5b7f);if(!_0x9dccd8||!['javascript',_0x7cef26(0xb6),'python']['includes'](_0x9dccd8))return{'file':this['directoryAccessManager'][_0x7cef26(0xa5)](_0x2a5b7f,_0xd215a8),'fullPath':_0x2a5b7f,'language':_0x9dccd8||_0x7cef26(0x105),'issues':[],'skipped':!![],'skipReason':'Security\x20scanning\x20only\x20supports\x20JavaScript,\x20TypeScript,\x20and\x20Python\x20files'};const _0x500dd5=await a0_0x367898['readFile'](_0x2a5b7f,'utf-8'),_0x43dd7c=await this['getSecurityAnalyzer'](),_0x1b51c8=await _0x43dd7c[_0x7cef26(0x72)](_0x2a5b7f,_0x500dd5,{'skipTestFiles':_0x5330bb['skipTestFiles']!==![]}),_0x17409f={'file':this[_0x7cef26(0x97)]['createRelativePath'](_0x2a5b7f,_0xd215a8),'fullPath':_0x2a5b7f,'language':_0x9dccd8,'action':_0x7cef26(0x102),'critical':_0x1b51c8[_0x7cef26(0xa2)](_0x5d356b=>_0x5d356b[_0x7cef26(0xb4)]===STATIC_ANALYSIS['SEVERITY'][_0x7cef26(0x11b)]),'errors':_0x1b51c8[_0x7cef26(0xa2)](_0x1e1c82=>_0x1e1c82[_0x7cef26(0xb4)]===STATIC_ANALYSIS['SEVERITY']['ERROR']),'warnings':_0x1b51c8[_0x7cef26(0xa2)](_0x348f4a=>_0x348f4a[_0x7cef26(0xb4)]===STATIC_ANALYSIS[_0x7cef26(0xe8)]['WARNING']),'info':_0x1b51c8['filter'](_0x192ae4=>_0x192ae4['severity']===STATIC_ANALYSIS['SEVERITY']['INFO']),'totalIssues':_0x1b51c8['length'],'analyzed':!![],'scannersUsed':_0x1b51c8['map'](_0x45c7a7=>_0x45c7a7[_0x7cef26(0x74)])[_0x7cef26(0xa2)]((_0x3dc3bf,_0x405b56,_0x3d7aba)=>_0x3d7aba[_0x7cef26(0x140)](_0x3dc3bf)===_0x405b56),'timestamp':new Date()[_0x7cef26(0x88)]()};return _0x17409f;}catch(_0x8dc49f){throw new Error('Failed\x20to\x20security\x20scan\x20'+_0x4d4a50+':\x20'+_0x8dc49f['message']);}}async['securityScanProject'](_0x334603,_0x5f3d68,_0x357a77,_0x16bdbb,_0x2bad6d={}){const _0xa5d8ae=a0_0x3e94ea,_0x2539ba=a0_0x475713[_0xa5d8ae(0xa7)](_0x334603)?a0_0x475713['normalize'](_0x334603):a0_0x475713[_0xa5d8ae(0x11d)](_0x357a77,_0x334603),_0x33e06a=this['directoryAccessManager'][_0xa5d8ae(0xdb)](_0x2539ba,_0x16bdbb);if(!_0x33e06a['allowed'])throw new Error('Read\x20access\x20denied:\x20'+_0x33e06a['reason']);const _0x4d88d3=await this['getSecurityAnalyzer'](),_0x33ef9f=await _0x4d88d3[_0xa5d8ae(0x10b)](_0x2539ba,_0xa5d8ae(0xc2),_0x2bad6d),_0x50d64d=_0x5f3d68||'**/*.{js,jsx,mjs,cjs,ts,tsx,py}',_0x546a68=await this[_0xa5d8ae(0x7c)](_0x2539ba,_0x50d64d);if(_0x546a68[_0xa5d8ae(0x8e)]>this['maxFilesPerBatch'])throw new Error('Too\x20many\x20files:\x20'+_0x546a68['length']+'\x20(max\x20'+this[_0xa5d8ae(0x126)]+')');const _0x4bde0a=[];if(this['parallelAnalysis']&&_0x546a68[_0xa5d8ae(0x8e)]>0x1){this['logger']?.['debug']('Using\x20parallel\x20security\x20scanning',{'totalFiles':_0x546a68[_0xa5d8ae(0x8e)],'batchSize':this[_0xa5d8ae(0xea)]});for(let _0x4537be=0x0;_0x4537be<_0x546a68['length'];_0x4537be+=this[_0xa5d8ae(0xea)]){const _0x6c5d59=_0x546a68['slice'](_0x4537be,_0x4537be+this['maxParallelFiles']);_0x2bad6d['onProgress']&&_0x2bad6d['onProgress']({'completed':_0x4537be,'total':_0x546a68[_0xa5d8ae(0x8e)],'percentage':Math['round'](_0x4537be/_0x546a68['length']*0x64)});const _0x35ea20=_0x6c5d59[_0xa5d8ae(0xd1)](async _0x4f7168=>{const _0x18ee90=_0xa5d8ae;try{return await this[_0x18ee90(0x80)](_0x4f7168,_0x357a77,_0x16bdbb,_0x2bad6d);}catch(_0x191313){return this['logger']?.['warn']('Failed\x20to\x20security\x20scan\x20file\x20in\x20project',{'file':_0x4f7168,'error':_0x191313[_0x18ee90(0x6b)]}),{'file':this[_0x18ee90(0x97)][_0x18ee90(0xa5)](_0x4f7168,_0x16bdbb),'fullPath':_0x4f7168,'error':_0x191313[_0x18ee90(0x6b)],'success':![]};}}),_0x563104=await Promise['all'](_0x35ea20);_0x4bde0a[_0xa5d8ae(0xc6)](..._0x563104['filter'](_0x346b39=>_0x346b39!==null));}_0x2bad6d[_0xa5d8ae(0xa1)]&&_0x2bad6d[_0xa5d8ae(0xa1)]({'completed':_0x546a68['length'],'total':_0x546a68['length'],'percentage':0x64});}else for(const _0x363986 of _0x546a68){try{const _0x430181=await this[_0xa5d8ae(0x80)](_0x363986,_0x357a77,_0x16bdbb,_0x2bad6d);_0x430181&&_0x4bde0a[_0xa5d8ae(0xc6)](_0x430181);}catch(_0x52a67e){this[_0xa5d8ae(0x128)]?.[_0xa5d8ae(0x82)]('Failed\x20to\x20security\x20scan\x20file\x20in\x20project',{'file':_0x363986,'error':_0x52a67e['message']}),_0x4bde0a[_0xa5d8ae(0xc6)]({'file':this[_0xa5d8ae(0x97)]['createRelativePath'](_0x363986,_0x16bdbb),'fullPath':_0x363986,'error':_0x52a67e['message'],'success':![]});}}return _0x33ef9f[_0xa5d8ae(0x8e)]>0x0&&_0x4bde0a['push']({'file':a0_0x475713['join'](_0x2539ba,'package.json'),'fullPath':a0_0x475713[_0xa5d8ae(0x10d)](_0x2539ba,_0xa5d8ae(0x107)),'action':'dependency-scan','critical':_0x33ef9f['filter'](_0x48565f=>_0x48565f[_0xa5d8ae(0xb4)]===STATIC_ANALYSIS[_0xa5d8ae(0xe8)][_0xa5d8ae(0x11b)]),'errors':_0x33ef9f['filter'](_0x147285=>_0x147285['severity']===STATIC_ANALYSIS[_0xa5d8ae(0xe8)]['ERROR']),'warnings':_0x33ef9f['filter'](_0x37a55b=>_0x37a55b[_0xa5d8ae(0xb4)]===STATIC_ANALYSIS[_0xa5d8ae(0xe8)]['WARNING']),'info':_0x33ef9f['filter'](_0x36b73b=>_0x36b73b[_0xa5d8ae(0xb4)]===STATIC_ANALYSIS[_0xa5d8ae(0xe8)]['INFO']),'totalIssues':_0x33ef9f['length'],'analyzed':!![],'scannersUsed':['npm-audit'],'timestamp':new Date()['toISOString']()}),_0x4bde0a;}async[a0_0x3e94ea(0x6e)](_0x226509,_0x33ed0a,_0x2c087d,_0x49e1e2={}){const _0x3dedc2=a0_0x3e94ea,_0x1f6f28=a0_0x475713['isAbsolute'](_0x226509)?a0_0x475713['normalize'](_0x226509):a0_0x475713['resolve'](_0x33ed0a,_0x226509),_0x271a65=this['directoryAccessManager'][_0x3dedc2(0xdb)](_0x1f6f28,_0x2c087d);if(!_0x271a65['allowed'])throw new Error('Read\x20access\x20denied:\x20'+_0x271a65[_0x3dedc2(0x12b)]);try{const _0x560a1a=await a0_0x367898[_0x3dedc2(0xa9)](_0x1f6f28);if(_0x560a1a[_0x3dedc2(0x7f)]>this[_0x3dedc2(0x93)])throw new Error(_0x3dedc2(0xbb)+_0x560a1a['size']+'\x20bytes\x20(max\x20'+this['maxFileSize']+')');const _0x28ed93=await this['getConfigValidator'](),_0x49f04c=await _0x28ed93[_0x3dedc2(0xd4)](_0x1f6f28,_0x49e1e2),_0x26709d={'file':this[_0x3dedc2(0x97)][_0x3dedc2(0xa5)](_0x1f6f28,_0x2c087d),'fullPath':_0x1f6f28,'action':_0x3dedc2(0x145),'critical':_0x49f04c['filter'](_0x156fe5=>_0x156fe5[_0x3dedc2(0xb4)]===STATIC_ANALYSIS[_0x3dedc2(0xe8)][_0x3dedc2(0x11b)]),'errors':_0x49f04c['filter'](_0x7f2b60=>_0x7f2b60['severity']===STATIC_ANALYSIS[_0x3dedc2(0xe8)][_0x3dedc2(0x118)]),'warnings':_0x49f04c[_0x3dedc2(0xa2)](_0x3a4a56=>_0x3a4a56['severity']===STATIC_ANALYSIS['SEVERITY'][_0x3dedc2(0x11a)]),'info':_0x49f04c['filter'](_0x375427=>_0x375427['severity']===STATIC_ANALYSIS['SEVERITY'][_0x3dedc2(0xe1)]),'totalIssues':_0x49f04c['length'],'analyzed':!![],'validatorsUsed':_0x49f04c[_0x3dedc2(0xd1)](_0x539ab0=>_0x539ab0['validator'])['filter']((_0x490a17,_0x3f15dc,_0x2b986d)=>_0x2b986d[_0x3dedc2(0x140)](_0x490a17)===_0x3f15dc),'timestamp':new Date()[_0x3dedc2(0x88)]()};return _0x26709d;}catch(_0x4c27a2){throw new Error('Failed\x20to\x20validate\x20config\x20'+_0x226509+':\x20'+_0x4c27a2[_0x3dedc2(0x6b)]);}}async['validateConfigDirectory'](_0xa62675,_0x281e23,_0x1211aa,_0x1eeb95={}){const _0x1642b6=a0_0x3e94ea,_0x2d1378=a0_0x475713['isAbsolute'](_0xa62675)?a0_0x475713[_0x1642b6(0x12a)](_0xa62675):a0_0x475713[_0x1642b6(0x11d)](_0x281e23,_0xa62675),_0x22ee4a=this[_0x1642b6(0x97)][_0x1642b6(0xdb)](_0x2d1378,_0x1211aa);if(!_0x22ee4a['allowed'])throw new Error(_0x1642b6(0xa8)+_0x22ee4a[_0x1642b6(0x12b)]);const _0x38414b=await this['findConfigFiles'](_0x2d1378);if(_0x38414b[_0x1642b6(0x8e)]>this['maxFilesPerBatch'])throw new Error('Too\x20many\x20config\x20files:\x20'+_0x38414b[_0x1642b6(0x8e)]+_0x1642b6(0x135)+this[_0x1642b6(0x126)]+')');const _0x39c734=[];for(const _0x5498a0 of _0x38414b){try{const _0x1391ef=await this['validateConfigFile'](_0x5498a0,_0x281e23,_0x1211aa,_0x1eeb95);_0x1391ef&&_0x39c734[_0x1642b6(0xc6)](_0x1391ef);}catch(_0x3bc3df){this['logger']?.['warn'](_0x1642b6(0xf5),{'file':_0x5498a0,'error':_0x3bc3df['message']}),_0x39c734['push']({'file':this['directoryAccessManager']['createRelativePath'](_0x5498a0,_0x1211aa),'fullPath':_0x5498a0,'error':_0x3bc3df['message'],'success':![]});}}return _0x39c734;}async[a0_0x3e94ea(0xda)](_0x391bed){const _0x98e8d1=a0_0x3e94ea,_0x30319e=[],_0x4bb888=['package.json',_0x98e8d1(0xd7),_0x98e8d1(0xf9),'docker-compose.yml','docker-compose.yaml',_0x98e8d1(0xcf),_0x98e8d1(0x134),'.eslintrc.js',_0x98e8d1(0xcd),_0x98e8d1(0x7b),'.prettierrc.json'],_0x6a59dd=['.yml','.yaml','.json','.tf','.tfvars'],_0x2d3224=async _0x4236b2=>{const _0x1b8a9e=_0x98e8d1,_0x5ccdd2=await a0_0x367898['readdir'](_0x4236b2,{'withFileTypes':!![]});for(const _0x2eed84 of _0x5ccdd2){const _0x3563b0=a0_0x475713['join'](_0x4236b2,_0x2eed84[_0x1b8a9e(0xaa)]);if(_0x2eed84['isDirectory']()){if(_0x2eed84['name']===_0x1b8a9e(0xd2)||_0x2eed84[_0x1b8a9e(0xaa)]===_0x1b8a9e(0xbf)||_0x2eed84[_0x1b8a9e(0xaa)]===_0x1b8a9e(0xb7)||_0x2eed84['name']==='terraform')await _0x2d3224(_0x3563b0);else{if(!['node_modules','.git',_0x1b8a9e(0x6d),'build'][_0x1b8a9e(0x120)](_0x2eed84['name']))continue;}}else{if(_0x2eed84['isFile']()){if(_0x4bb888[_0x1b8a9e(0x120)](_0x2eed84[_0x1b8a9e(0xaa)]))_0x30319e['push'](_0x3563b0);else{const _0x165c7e=a0_0x475713['extname'](_0x2eed84[_0x1b8a9e(0xaa)])[_0x1b8a9e(0xfa)]();if(_0x6a59dd[_0x1b8a9e(0x120)](_0x165c7e)){const _0xe3d65e=a0_0x475713['basename'](a0_0x475713['dirname'](_0x3563b0));(_0xe3d65e===_0x1b8a9e(0xbf)||_0xe3d65e==='k8s'||_0xe3d65e===_0x1b8a9e(0x101)||_0xe3d65e==='workflows')&&_0x30319e[_0x1b8a9e(0xc6)](_0x3563b0);}}}}}};return await _0x2d3224(_0x391bed),_0x30319e;}[a0_0x3e94ea(0x139)](_0x151448){const _0x1bb5f9=a0_0x3e94ea,_0x5d2537=a0_0x475713[_0x1bb5f9(0xbd)](_0x151448)['toLowerCase']();return STATIC_ANALYSIS[_0x1bb5f9(0x11c)][_0x5d2537]||null;}async[a0_0x3e94ea(0xba)](_0x26d9ec,_0x3e99f9){const _0xc62e2f=a0_0x3e94ea;try{if(_0x3e99f9===STATIC_ANALYSIS[_0xc62e2f(0xf8)][_0xc62e2f(0xd6)]||_0x3e99f9===STATIC_ANALYSIS[_0xc62e2f(0xf8)][_0xc62e2f(0x129)])return await this['detectJSFramework'](_0x26d9ec);if(_0x3e99f9===STATIC_ANALYSIS['LANGUAGE'][_0xc62e2f(0x89)])return await this[_0xc62e2f(0x95)](_0x26d9ec);return null;}catch(_0x372ebb){return this['logger']?.['debug'](_0xc62e2f(0x98),{'error':_0x372ebb['message']}),null;}}async['detectJSFramework'](_0x3d9083){const _0x39283d=a0_0x3e94ea;try{const _0x6f44d5=a0_0x475713[_0x39283d(0x10d)](_0x3d9083,STATIC_ANALYSIS[_0x39283d(0xf0)]['JAVASCRIPT']),_0x6018bf=await a0_0x367898['readFile'](_0x6f44d5,_0x39283d(0x12c)),_0x1905a3=JSON[_0x39283d(0x10f)](_0x6018bf),_0x5b2403={..._0x1905a3['dependencies'],..._0x1905a3[_0x39283d(0x13a)]};for(const [_0x2e59a6,_0x773623]of Object['entries'](STATIC_ANALYSIS[_0x39283d(0xc8)])){if(_0x5b2403[_0x773623])return _0x2e59a6[_0x39283d(0xfa)]();}return null;}catch(_0x4296e0){return null;}}async[a0_0x3e94ea(0x95)](_0x17ee0b){const _0x234027=a0_0x3e94ea;try{const _0x2085d8=a0_0x475713[_0x234027(0x10d)](_0x17ee0b,STATIC_ANALYSIS[_0x234027(0xf0)]['PYTHON']),_0x7e70eb=await a0_0x367898['readFile'](_0x2085d8,_0x234027(0x12c));for(const [_0x101253,_0x21b058]of Object[_0x234027(0xfe)](STATIC_ANALYSIS['PYTHON_FRAMEWORKS'])){if(_0x7e70eb['toLowerCase']()['includes'](_0x21b058))return _0x101253[_0x234027(0xfa)]();}return null;}catch(_0xe0c3a2){try{const _0x5c5adb=a0_0x475713['join'](_0x17ee0b,STATIC_ANALYSIS['FRAMEWORK_MANIFESTS'][_0x234027(0xce)]),_0x454dbc=await a0_0x367898[_0x234027(0xdc)](_0x5c5adb,'utf-8');for(const [_0x5c8853,_0x392760]of Object[_0x234027(0xfe)](STATIC_ANALYSIS['PYTHON_FRAMEWORKS'])){if(_0x454dbc['toLowerCase']()['includes'](_0x392760))return _0x5c8853['toLowerCase']();}}catch{}return null;}}async[a0_0x3e94ea(0x7c)](_0x4b5d6c,_0x36f503){const _0x562a47=a0_0x3e94ea,_0x3981f6=[],_0x32918d=_0x36f503||_0x562a47(0xed),_0x1c57a4=_0x22e1ca=>{const _0x415fcf=_0x562a47,_0x3e1bd5=[],_0x5b64b8=_0x22e1ca['match'](/\*\.\{([^}]+)\}/);if(_0x5b64b8){const _0x12acbb=_0x5b64b8[0x1]['split'](',')['map'](_0x430f27=>_0x430f27[_0x415fcf(0x13c)]());_0x12acbb['forEach'](_0x52699b=>_0x3e1bd5[_0x415fcf(0xc6)](_0x52699b[_0x415fcf(0xee)]('.')?_0x52699b:'.'+_0x52699b));}else{const _0x9677ee=_0x22e1ca[_0x415fcf(0xc0)](/\*\.([a-z]+)$/i);if(_0x9677ee){const _0x1e45a7=_0x9677ee[0x1];_0x3e1bd5[_0x415fcf(0xc6)](_0x1e45a7['startsWith']('.')?_0x1e45a7:'.'+_0x1e45a7);}}if(_0x3e1bd5['length']===0x0)return null;return _0x3e1bd5;},_0x2b91a5=_0x1c57a4(_0x32918d),_0x58ae55=async _0x5b75c3=>{const _0x127ef7=_0x562a47,_0xd55d28=await a0_0x367898['readdir'](_0x5b75c3,{'withFileTypes':!![]});for(const _0x386814 of _0xd55d28){const _0x42dae6=a0_0x475713['join'](_0x5b75c3,_0x386814[_0x127ef7(0xaa)]);if(_0x386814['isDirectory']())![_0x127ef7(0x8a),'.git',_0x127ef7(0x6d),'build',_0x127ef7(0xa4),'.venv',_0x127ef7(0x103)]['includes'](_0x386814[_0x127ef7(0xaa)])&&await _0x58ae55(_0x42dae6);else{if(_0x386814['isFile']()){const _0x46a43c=a0_0x475713[_0x127ef7(0xbd)](_0x386814['name'])['toLowerCase']();STATIC_ANALYSIS['EXTENSION_TO_LANGUAGE'][_0x46a43c]&&((_0x2b91a5===null||_0x2b91a5[_0x127ef7(0x120)](_0x46a43c))&&_0x3981f6['push'](_0x42dae6));}}}};return await _0x58ae55(_0x4b5d6c),_0x3981f6;}async[a0_0x3e94ea(0x69)](_0x6fd9c3){const _0x470678=a0_0x3e94ea;try{if(_0x6fd9c3===STATIC_ANALYSIS['LANGUAGE']['JAVASCRIPT']){if(!this['analyzers']['javascript']){const {default:_0x293378}=await import(_0x470678(0x124));this[_0x470678(0x143)][_0x470678(0xc2)]=new _0x293378(this[_0x470678(0x128)]);}return this[_0x470678(0x143)]['javascript'];}if(_0x6fd9c3===STATIC_ANALYSIS[_0x470678(0xf8)]['TYPESCRIPT']){if(!this['analyzers'][_0x470678(0xb6)]){const {default:_0x41faf2}=await import('../analyzers/TypeScriptAnalyzer.js');this['analyzers'][_0x470678(0xb6)]=new _0x41faf2(this['logger']);}return this[_0x470678(0x143)][_0x470678(0xb6)];}if(_0x6fd9c3===STATIC_ANALYSIS['LANGUAGE']['PYTHON']){if(!this[_0x470678(0x143)][_0x470678(0x13e)]){const {default:_0x5232bd}=await import('../analyzers/PythonAnalyzer.js');this[_0x470678(0x143)]['python']=new _0x5232bd(this[_0x470678(0x128)]);}return this[_0x470678(0x143)]['python'];}if(_0x6fd9c3===STATIC_ANALYSIS['LANGUAGE']['CSS']||_0x6fd9c3===STATIC_ANALYSIS['LANGUAGE'][_0x470678(0x10c)]||_0x6fd9c3===STATIC_ANALYSIS[_0x470678(0xf8)][_0x470678(0xd0)]){if(!this['analyzers']['css']){const {default:_0x4c7bcc}=await import('../analyzers/CSSAnalyzer.js');this[_0x470678(0x143)]['css']=new _0x4c7bcc(this[_0x470678(0x128)]);}return this[_0x470678(0x143)]['css'];}return null;}catch(_0x1617ea){return this[_0x470678(0x128)]?.['error']('Failed\x20to\x20load\x20analyzer',{'language':_0x6fd9c3,'error':_0x1617ea[_0x470678(0x6b)]}),null;}}async[a0_0x3e94ea(0xe0)](){const _0x1c0bca=a0_0x3e94ea;if(!this[_0x1c0bca(0x143)]['eslint']){const {default:_0x2d2b10}=await import(_0x1c0bca(0x75));this[_0x1c0bca(0x143)][_0x1c0bca(0x113)]=new _0x2d2b10(this[_0x1c0bca(0x128)]);}return this['analyzers'][_0x1c0bca(0x113)];}async['getPrettierFormatter'](){const _0x3f801f=a0_0x3e94ea;if(!this[_0x3f801f(0xeb)][_0x3f801f(0x114)]){const {default:_0x118404}=await import(_0x3f801f(0x136));this['formatters']['prettier']=new _0x118404(this[_0x3f801f(0x128)]);}return this[_0x3f801f(0xeb)]['prettier'];}async['getSecurityAnalyzer'](){const _0x3c19dc=a0_0x3e94ea;if(!this['analyzers'][_0x3c19dc(0x11f)]){const {default:_0x446bd7}=await import('../analyzers/SecurityAnalyzer.js');this['analyzers']['security']=new _0x446bd7(this['logger']);}return this[_0x3c19dc(0x143)][_0x3c19dc(0x11f)];}async['getConfigValidator'](){const _0x419878=a0_0x3e94ea;if(!this[_0x419878(0x143)][_0x419878(0xd8)]){const {default:_0x58f8a0}=await import('../analyzers/ConfigValidator.js');this[_0x419878(0x143)][_0x419878(0xd8)]=new _0x58f8a0(this[_0x419878(0x128)]);}return this['analyzers']['config'];}[a0_0x3e94ea(0x76)](_0x27a389,_0xec4ab2){const _0x1424f6=a0_0x3e94ea;if(_0xec4ab2['analyzed']){_0x27a389['totalFiles']++;const _0x55da0c=_0xec4ab2['critical']?.[_0x1424f6(0x8e)]||0x0,_0x71ef03=_0xec4ab2['errors']?.[_0x1424f6(0x8e)]||0x0,_0x1c5e9f=_0xec4ab2[_0x1424f6(0xde)]?.['length']||0x0,_0x145e51=_0xec4ab2[_0x1424f6(0x147)]?.[_0x1424f6(0x8e)]||0x0;_0x27a389[_0x1424f6(0x10e)]===undefined&&(_0x27a389['totalCritical']=0x0);_0x27a389[_0x1424f6(0x10e)]+=_0x55da0c,_0x27a389[_0x1424f6(0x116)]+=_0x71ef03,_0x27a389['totalWarnings']+=_0x1c5e9f,_0x27a389['totalInfo']+=_0x145e51;(_0x55da0c>0x0||_0x71ef03>0x0)&&_0x27a389['filesWithErrors']++;_0xec4ab2[_0x1424f6(0x125)]&&(_0x27a389['filesByLanguage'][_0xec4ab2[_0x1424f6(0x125)]]=(_0x27a389['filesByLanguage'][_0xec4ab2['language']]||0x0)+0x1);const _0x3e9c4e=[..._0xec4ab2[_0x1424f6(0xe4)]||[],..._0xec4ab2['errors']||[],..._0xec4ab2[_0x1424f6(0xde)]||[]];for(const _0x16b89b of _0x3e9c4e){_0x16b89b['category']&&(_0x27a389[_0x1424f6(0x119)][_0x16b89b['category']]=(_0x27a389[_0x1424f6(0x119)][_0x16b89b['category']]||0x0)+0x1);}}}[a0_0x3e94ea(0xca)](_0x44ea00){const _0x568317=a0_0x3e94ea;return a0_0x444804['createHash'](_0x568317(0x109))['update'](_0x44ea00)[_0x568317(0x7a)](_0x568317(0xb2))[_0x568317(0x13b)](0x0,0x10);}['getPerformanceMetrics'](){const _0x141f98=a0_0x3e94ea,_0x42d99c=this[_0x141f98(0xbe)][_0x141f98(0xd5)]>0x0?this['metrics'][_0x141f98(0x115)]/this['metrics'][_0x141f98(0xd5)]*0x64:0x0,_0x434d7c=this[_0x141f98(0xbe)]['filesAnalyzed']>0x0?this[_0x141f98(0xbe)]['totalAnalysisTime']/this[_0x141f98(0xbe)]['filesAnalyzed']:0x0;return{...this['metrics'],'cacheHitRate':Math[_0x141f98(0x7d)](_0x42d99c*0xa)/0xa,'averageAnalysisTime':Math[_0x141f98(0x7d)](_0x434d7c),'cacheSize':this[_0x141f98(0xc4)][_0x141f98(0x7f)]};}[a0_0x3e94ea(0xfb)](){const _0x5219cc=a0_0x3e94ea;this[_0x5219cc(0xbe)]={'totalAnalyses':0x0,'cacheHits':0x0,'cacheMisses':0x0,'totalAnalysisTime':0x0,'filesAnalyzed':0x0,'parallelBatches':0x0};}[a0_0x3e94ea(0x8d)](){const _0x57bebb=a0_0x3e94ea;this[_0x57bebb(0xc4)][_0x57bebb(0x94)](),this[_0x57bebb(0x128)]?.['debug'](_0x57bebb(0x8f));}[a0_0x3e94ea(0x12d)](){const _0x59d83d=a0_0x3e94ea;return[_0x59d83d(0x72),_0x59d83d(0x106),'fix','format',_0x59d83d(0x102),_0x59d83d(0x110),'validate-config','validate-config-directory'];}[a0_0x3e94ea(0x12e)](){const _0x1f9943=a0_0x3e94ea;return{'type':_0x1f9943(0xf7),'properties':{'actions':{'type':_0x1f9943(0x11e),'minItems':0x1,'items':{'type':_0x1f9943(0xf7),'properties':{'type':{'type':'string','enum':this['getSupportedActions']()},'filePath':{'type':_0x1f9943(0xbc)},'directory':{'type':'string'},'pattern':{'type':_0x1f9943(0xbc)},'includeWarnings':{'type':'boolean'},'maxErrors':{'type':'number'}},'required':[_0x1f9943(0xa0)]}}},'required':[_0x1f9943(0xc3)]};}}export default StaticAnalysisTool;