@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,247 +1 @@
1
- /**
2
- * PrettierFormatter - Code formatting using Prettier
3
- *
4
- * Purpose:
5
- * - Format code according to consistent style rules
6
- * - Support multiple languages (JS, TS, CSS, HTML, JSON, etc.)
7
- * - Detect and use project's Prettier configuration
8
- * - Provide before/after comparison
9
- */
10
-
11
- import prettier from 'prettier';
12
- import path from 'path';
13
- import fs from 'fs/promises';
14
-
15
- class PrettierFormatter {
16
- constructor(logger = null) {
17
- this.logger = logger;
18
- this.configCache = new Map();
19
- }
20
-
21
- /**
22
- * Format code with Prettier
23
- * @param {string} filePath - Path to file
24
- * @param {string} content - File content
25
- * @param {Object} options - Format options
26
- * @returns {Promise<Object>} Formatted content and changes
27
- */
28
- async format(filePath, content, options = {}) {
29
- try {
30
- // Get Prettier configuration
31
- const config = await this.getPrettierConfig(filePath, options.workingDir);
32
-
33
- // Determine parser from file extension
34
- const parser = this.getParser(filePath);
35
-
36
- // Format the code
37
- const formatted = await prettier.format(content, {
38
- ...config,
39
- filepath: filePath,
40
- parser
41
- });
42
-
43
- // Check if formatting made changes
44
- const hasChanges = formatted !== content;
45
-
46
- return {
47
- formatted: hasChanges,
48
- content: formatted,
49
- original: content,
50
- changes: hasChanges ? this.describeChanges(content, formatted) : [],
51
- linesChanged: hasChanges ? this.countChangedLines(content, formatted) : 0
52
- };
53
-
54
- } catch (error) {
55
- this.logger?.error('Prettier formatting failed', {
56
- file: filePath,
57
- error: error.message
58
- });
59
-
60
- throw new Error(`Prettier formatting failed: ${error.message}`);
61
- }
62
- }
63
-
64
- /**
65
- * Check if file needs formatting
66
- * @param {string} filePath - Path to file
67
- * @param {string} content - File content
68
- * @param {Object} options - Check options
69
- * @returns {Promise<boolean>} True if file needs formatting
70
- */
71
- async check(filePath, content, options = {}) {
72
- try {
73
- const config = await this.getPrettierConfig(filePath, options.workingDir);
74
- const parser = this.getParser(filePath);
75
-
76
- const formatted = await prettier.format(content, {
77
- ...config,
78
- filepath: filePath,
79
- parser
80
- });
81
-
82
- return formatted !== content;
83
-
84
- } catch (error) {
85
- this.logger?.warn('Prettier check failed', {
86
- file: filePath,
87
- error: error.message
88
- });
89
-
90
- return false;
91
- }
92
- }
93
-
94
- /**
95
- * Get Prettier configuration
96
- * @private
97
- */
98
- async getPrettierConfig(filePath, workingDir) {
99
- // Check cache
100
- const cacheKey = workingDir || path.dirname(filePath);
101
- if (this.configCache.has(cacheKey)) {
102
- return this.configCache.get(cacheKey);
103
- }
104
-
105
- let config = {};
106
-
107
- // Try to load project's Prettier config
108
- if (workingDir) {
109
- try {
110
- const projectConfig = await prettier.resolveConfig(filePath, {
111
- config: workingDir
112
- });
113
-
114
- if (projectConfig) {
115
- this.logger?.debug('Found Prettier config', { workingDir });
116
- config = projectConfig;
117
- }
118
- } catch (error) {
119
- this.logger?.debug('No Prettier config found, using defaults');
120
- }
121
- }
122
-
123
- // Default configuration
124
- const defaultConfig = {
125
- semi: true,
126
- singleQuote: true,
127
- tabWidth: 2,
128
- trailingComma: 'es5',
129
- printWidth: 100,
130
- arrowParens: 'avoid',
131
- endOfLine: 'lf',
132
- ...config
133
- };
134
-
135
- // Cache the configuration
136
- this.configCache.set(cacheKey, defaultConfig);
137
-
138
- return defaultConfig;
139
- }
140
-
141
- /**
142
- * Get parser for file type
143
- * @private
144
- */
145
- getParser(filePath) {
146
- const ext = path.extname(filePath).toLowerCase();
147
-
148
- const parserMap = {
149
- '.js': 'babel',
150
- '.jsx': 'babel',
151
- '.mjs': 'babel',
152
- '.cjs': 'babel',
153
- '.ts': 'typescript',
154
- '.tsx': 'typescript',
155
- '.json': 'json',
156
- '.json5': 'json5',
157
- '.css': 'css',
158
- '.scss': 'scss',
159
- '.less': 'less',
160
- '.html': 'html',
161
- '.vue': 'vue',
162
- '.md': 'markdown',
163
- '.yaml': 'yaml',
164
- '.yml': 'yaml'
165
- };
166
-
167
- return parserMap[ext] || 'babel';
168
- }
169
-
170
- /**
171
- * Describe changes made by formatting
172
- * @private
173
- */
174
- describeChanges(original, formatted) {
175
- const changes = [];
176
- const originalLines = original.split('\n');
177
- const formattedLines = formatted.split('\n');
178
-
179
- const maxLines = Math.max(originalLines.length, formattedLines.length);
180
-
181
- for (let i = 0; i < maxLines; i++) {
182
- const origLine = originalLines[i];
183
- const formattedLine = formattedLines[i];
184
-
185
- if (origLine !== formattedLine) {
186
- changes.push({
187
- line: i + 1,
188
- type: origLine !== undefined && formattedLine !== undefined
189
- ? 'modified'
190
- : (origLine !== undefined ? 'removed' : 'added'),
191
- original: origLine || '',
192
- formatted: formattedLine || ''
193
- });
194
- }
195
- }
196
-
197
- return changes;
198
- }
199
-
200
- /**
201
- * Count changed lines
202
- * @private
203
- */
204
- countChangedLines(original, formatted) {
205
- const originalLines = original.split('\n');
206
- const formattedLines = formatted.split('\n');
207
- let changedCount = 0;
208
-
209
- const maxLines = Math.max(originalLines.length, formattedLines.length);
210
-
211
- for (let i = 0; i < maxLines; i++) {
212
- if (originalLines[i] !== formattedLines[i]) {
213
- changedCount++;
214
- }
215
- }
216
-
217
- return changedCount;
218
- }
219
-
220
- /**
221
- * Get supported file extensions
222
- * @returns {Array<string>} Array of supported extensions
223
- */
224
- getSupportedExtensions() {
225
- return [
226
- '.js', '.jsx', '.mjs', '.cjs',
227
- '.ts', '.tsx',
228
- '.json', '.json5',
229
- '.css', '.scss', '.less',
230
- '.html', '.vue',
231
- '.md',
232
- '.yaml', '.yml'
233
- ];
234
- }
235
-
236
- /**
237
- * Check if file type is supported
238
- * @param {string} filePath - Path to file
239
- * @returns {boolean} True if supported
240
- */
241
- isSupported(filePath) {
242
- const ext = path.extname(filePath).toLowerCase();
243
- return this.getSupportedExtensions().includes(ext);
244
- }
245
- }
246
-
247
- export default PrettierFormatter;
1
+ const a0_0x50cd34=a0_0x27ce;function a0_0x198a(){const _0x57c6eb=['Dg9mB3DLCKnHC2u','BgvUz3rO','lMPZB24','lMPZB241','DhLWzxnJCMLWDa','ntvdDM9SwMK','nJi0mtCXv0DfC0Lg','mJa1nJmYmgTytuzetq','mJu5otq0wxLLqKTW','mte3nta4otzyyuLou0C','ywrKzwq','rM91BMqGuhjLDhrPzxiGy29UzMLN','lNLHBwW','AhrTBa','z2v0uhjLDhrPzxjdB25MAwC','z2v0u3vWCg9YDgvKrxH0zw5ZAw9UCW','BwvZC2fNzq','Bwf4','zgvZy3jPyMvdAgfUz2vZ','y291BNrdAgfUz2vKtgLUzxm','lM1QCW','D29YA2LUz0rPCG','lMPZ','C3bSAxq','yMfIzwW','CMvTB3zLza','lNrZEa','nZmWnZzZuMX0zLu','y29UzMLNq2fJAgu','y2HLy2S','ANnVBG','D2fYBG','zM9YBwf0','zgvIDwC','C2nZCW','mtG5mZyWAeXWBNj6','z2v0','y3nZ','zxjYB3i','mZq2nJqWq2nvuuDr','Bg9Nz2vY'];a0_0x198a=function(){return _0x57c6eb;};return a0_0x198a();}function a0_0x27ce(_0x295608,_0x4b4c20){_0x295608=_0x295608-0x135;const _0x198ab2=a0_0x198a();let _0x27ce59=_0x198ab2[_0x295608];if(a0_0x27ce['QPQlvU']===undefined){var _0xda1fbd=function(_0x2edf93){const _0xdf7acf='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x48dcdd='',_0x5a014d='';for(let _0x25c1d6=0x0,_0x3435da,_0x649507,_0x8f4946=0x0;_0x649507=_0x2edf93['charAt'](_0x8f4946++);~_0x649507&&(_0x3435da=_0x25c1d6%0x4?_0x3435da*0x40+_0x649507:_0x649507,_0x25c1d6++%0x4)?_0x48dcdd+=String['fromCharCode'](0xff&_0x3435da>>(-0x2*_0x25c1d6&0x6)):0x0){_0x649507=_0xdf7acf['indexOf'](_0x649507);}for(let _0x2681b8=0x0,_0x5c0e0a=_0x48dcdd['length'];_0x2681b8<_0x5c0e0a;_0x2681b8++){_0x5a014d+='%'+('00'+_0x48dcdd['charCodeAt'](_0x2681b8)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x5a014d);};a0_0x27ce['XBauih']=_0xda1fbd,a0_0x27ce['TGJBWJ']={},a0_0x27ce['QPQlvU']=!![];}const _0x3c341c=_0x198ab2[0x0],_0x40b3dc=_0x295608+_0x3c341c,_0x4cb882=a0_0x27ce['TGJBWJ'][_0x40b3dc];return!_0x4cb882?(_0x27ce59=a0_0x27ce['XBauih'](_0x27ce59),a0_0x27ce['TGJBWJ'][_0x40b3dc]=_0x27ce59):_0x27ce59=_0x4cb882,_0x27ce59;}(function(_0x41c6aa,_0x5524d8){const _0x465929=a0_0x27ce,_0x3b8c60=_0x41c6aa();while(!![]){try{const _0x2d0271=-parseInt(_0x465929(0x148))/0x1+-parseInt(_0x465929(0x152))/0x2+-parseInt(_0x465929(0x150))/0x3+parseInt(_0x465929(0x13c))/0x4*(-parseInt(_0x465929(0x14f))/0x5)+-parseInt(_0x465929(0x144))/0x6+-parseInt(_0x465929(0x151))/0x7+parseInt(_0x465929(0x153))/0x8;if(_0x2d0271===_0x5524d8)break;else _0x3b8c60['push'](_0x3b8c60['shift']());}catch(_0x21a1f9){_0x3b8c60['push'](_0x3b8c60['shift']());}}}(a0_0x198a,0x3ef7a));import a0_0x48dcdd from'prettier';import a0_0x5a014d from'path';import a0_0x25c1d6 from'fs/promises';class PrettierFormatter{constructor(_0x3435da=null){const _0x37d4a6=a0_0x27ce;this['logger']=_0x3435da,this[_0x37d4a6(0x13d)]=new Map();}async[a0_0x50cd34(0x141)](_0x649507,_0x8f4946,_0x2681b8={}){const _0x36ca43=a0_0x50cd34;try{const _0x5c0e0a=await this[_0x36ca43(0x158)](_0x649507,_0x2681b8[_0x36ca43(0x136)]),_0x194674=this['getParser'](_0x649507),_0x414ea4=await a0_0x48dcdd[_0x36ca43(0x141)](_0x8f4946,{..._0x5c0e0a,'filepath':_0x649507,'parser':_0x194674}),_0xc70a4c=_0x414ea4!==_0x8f4946;return{'formatted':_0xc70a4c,'content':_0x414ea4,'original':_0x8f4946,'changes':_0xc70a4c?this[_0x36ca43(0x15c)](_0x8f4946,_0x414ea4):[],'linesChanged':_0xc70a4c?this[_0x36ca43(0x15d)](_0x8f4946,_0x414ea4):0x0};}catch(_0x39f6bd){this[_0x36ca43(0x149)]?.[_0x36ca43(0x147)]('Prettier\x20formatting\x20failed',{'file':_0x649507,'error':_0x39f6bd['message']});throw new Error('Prettier\x20formatting\x20failed:\x20'+_0x39f6bd[_0x36ca43(0x15a)]);}}async[a0_0x50cd34(0x13e)](_0x2245d2,_0x42bb0e,_0x3aed8d={}){const _0xffdf6f=a0_0x50cd34;try{const _0x192ac7=await this[_0xffdf6f(0x158)](_0x2245d2,_0x3aed8d[_0xffdf6f(0x136)]),_0x1de27e=this['getParser'](_0x2245d2),_0x51cb8f=await a0_0x48dcdd[_0xffdf6f(0x141)](_0x42bb0e,{..._0x192ac7,'filepath':_0x2245d2,'parser':_0x1de27e});return _0x51cb8f!==_0x42bb0e;}catch(_0x4ae5b1){return this[_0xffdf6f(0x149)]?.[_0xffdf6f(0x140)]('Prettier\x20check\x20failed',{'file':_0x2245d2,'error':_0x4ae5b1[_0xffdf6f(0x15a)]}),![];}}async[a0_0x50cd34(0x158)](_0x4ca15a,_0x407fa9){const _0x3bf877=a0_0x50cd34,_0x5cfcd8=_0x407fa9||a0_0x5a014d['dirname'](_0x4ca15a);if(this['configCache']['has'](_0x5cfcd8))return this['configCache'][_0x3bf877(0x145)](_0x5cfcd8);let _0x21a0a7={};if(_0x407fa9)try{const _0x3e2b3b=await a0_0x48dcdd['resolveConfig'](_0x4ca15a,{'config':_0x407fa9});_0x3e2b3b&&(this[_0x3bf877(0x149)]?.[_0x3bf877(0x142)](_0x3bf877(0x155),{'workingDir':_0x407fa9}),_0x21a0a7=_0x3e2b3b);}catch(_0x1c98c6){this['logger']?.[_0x3bf877(0x142)]('No Prettier config found, using defaults');}const defaultConfig={'semi':!![],'singleQuote':!![],'tabWidth':0x2,'trailingComma':'es5','printWidth':0x64,'arrowParens':'avoid','endOfLine':'lf',..._0x21a0a7};return this[_0x3bf877(0x13d)]['set'](_0x5cfcd8,defaultConfig),defaultConfig;}['getParser'](_0x13623b){const _0x2241b7=a0_0x50cd34,_0x40887b=a0_0x5a014d['extname'](_0x13623b)[_0x2241b7(0x14a)](),_0x36a93d={'.js':_0x2241b7(0x139),'.jsx':_0x2241b7(0x139),'.mjs':'babel','.cjs':_0x2241b7(0x139),'.ts':_0x2241b7(0x14e),'.tsx':_0x2241b7(0x14e),'.json':_0x2241b7(0x13f),'.json5':'json5','.css':_0x2241b7(0x146),'.scss':_0x2241b7(0x143),'.less':'less','.html':_0x2241b7(0x157),'.vue':'vue','.md':'markdown','.yaml':'yaml','.yml':'yaml'};return _0x36a93d[_0x40887b]||'babel';}[a0_0x50cd34(0x15c)](_0x1b4072,_0x4c5eaa){const _0x1b7b49=a0_0x50cd34,_0x406ab5=[],_0x436424=_0x1b4072[_0x1b7b49(0x138)]('\x0a'),_0x3b1d5d=_0x4c5eaa['split']('\x0a'),_0x654716=Math[_0x1b7b49(0x15b)](_0x436424[_0x1b7b49(0x14b)],_0x3b1d5d['length']);for(let _0xe78a1a=0x0;_0xe78a1a<_0x654716;_0xe78a1a++){const _0x502d7f=_0x436424[_0xe78a1a],_0x1cfb32=_0x3b1d5d[_0xe78a1a];_0x502d7f!==_0x1cfb32&&_0x406ab5['push']({'line':_0xe78a1a+0x1,'type':_0x502d7f!==undefined&&_0x1cfb32!==undefined?'modified':_0x502d7f!==undefined?_0x1b7b49(0x13a):_0x1b7b49(0x154),'original':_0x502d7f||'','formatted':_0x1cfb32||''});}return _0x406ab5;}['countChangedLines'](_0x3e3717,_0x2f193c){const _0x141211=a0_0x50cd34,_0xacf593=_0x3e3717['split']('\x0a'),_0x1e1d7f=_0x2f193c[_0x141211(0x138)]('\x0a');let _0x3460bd=0x0;const _0x556d7b=Math['max'](_0xacf593['length'],_0x1e1d7f[_0x141211(0x14b)]);for(let _0x8d972b=0x0;_0x8d972b<_0x556d7b;_0x8d972b++){_0xacf593[_0x8d972b]!==_0x1e1d7f[_0x8d972b]&&_0x3460bd++;}return _0x3460bd;}['getSupportedExtensions'](){const _0x4f5d6a=a0_0x50cd34;return[_0x4f5d6a(0x137),'.jsx',_0x4f5d6a(0x135),'.cjs','.ts',_0x4f5d6a(0x13b),_0x4f5d6a(0x14c),_0x4f5d6a(0x14d),'.css','.scss','.less','.html','.vue','.md',_0x4f5d6a(0x156),'.yml'];}['isSupported'](_0x3339e6){const _0x589006=a0_0x50cd34,_0x41e849=a0_0x5a014d['extname'](_0x3339e6)['toLowerCase']();return this[_0x589006(0x159)]()['includes'](_0x41e849);}}export default PrettierFormatter;
@@ -1,266 +1 @@
1
- /**
2
- * PythonAnalyzer - Python code analysis using Python's ast module
3
- *
4
- * Purpose:
5
- * - Analyze Python code for syntax errors
6
- * - Detect import issues
7
- * - Support Django, Flask, FastAPI frameworks
8
- * - Use Python's built-in ast module via subprocess
9
- */
10
-
11
- import { spawn } from 'child_process';
12
- import { STATIC_ANALYSIS } from '../utilities/constants.js';
13
- import fs from 'fs/promises';
14
- import path from 'path';
15
- import os from 'os';
16
-
17
- class PythonAnalyzer {
18
- constructor(logger = null) {
19
- this.logger = logger;
20
- this.pythonCommand = null;
21
- }
22
-
23
- /**
24
- * Analyze Python code
25
- * @param {string} filePath - Path to file
26
- * @param {string} content - File content
27
- * @param {Object} options - Analysis options
28
- * @returns {Promise<Array>} Array of diagnostics
29
- */
30
- async analyze(filePath, content, options = {}) {
31
- try {
32
- const diagnostics = [];
33
-
34
- // Check if Python is available
35
- const pythonCmd = await this.getPythonCommand();
36
- if (!pythonCmd) {
37
- this.logger?.warn('Python not available, skipping analysis');
38
- return [];
39
- }
40
-
41
- // Run syntax check using Python's ast module
42
- const syntaxErrors = await this.checkSyntax(filePath, content, pythonCmd);
43
- diagnostics.push(...syntaxErrors);
44
-
45
- this.logger?.debug('Python analysis completed', {
46
- file: filePath,
47
- totalDiagnostics: diagnostics.length,
48
- errors: diagnostics.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.ERROR).length,
49
- warnings: diagnostics.filter(d => d.severity === STATIC_ANALYSIS.SEVERITY.WARNING).length
50
- });
51
-
52
- return diagnostics;
53
-
54
- } catch (error) {
55
- this.logger?.error('Python analysis failed', {
56
- file: filePath,
57
- error: error.message
58
- });
59
-
60
- // Return empty array on error to allow other analysis to continue
61
- return [];
62
- }
63
- }
64
-
65
- /**
66
- * Check Python syntax using ast module
67
- * @private
68
- */
69
- async checkSyntax(filePath, content, pythonCmd) {
70
- const diagnostics = [];
71
-
72
- // Create a temporary Python script to check syntax
73
- const tempDir = os.tmpdir();
74
- const tempScript = path.join(tempDir, `syntax_check_${Date.now()}.py`);
75
- const tempFile = path.join(tempDir, `target_${Date.now()}.py`);
76
-
77
- try {
78
- // Write the content to a temporary file
79
- await fs.writeFile(tempFile, content, 'utf-8');
80
-
81
- // Create syntax checker script
82
- const checkerScript = `
83
- import ast
84
- import sys
85
- import json
86
-
87
- def check_syntax(filepath):
88
- try:
89
- with open(filepath, 'r', encoding='utf-8') as f:
90
- source = f.read()
91
-
92
- # Try to parse the file
93
- ast.parse(source, filename=filepath)
94
-
95
- # If successful, no errors
96
- print(json.dumps({"success": True, "errors": []}))
97
-
98
- except SyntaxError as e:
99
- error = {
100
- "file": filepath,
101
- "line": e.lineno or 1,
102
- "column": e.offset or 1,
103
- "message": str(e.msg),
104
- "text": e.text.strip() if e.text else ""
105
- }
106
- print(json.dumps({"success": False, "errors": [error]}))
107
-
108
- except Exception as e:
109
- error = {
110
- "file": filepath,
111
- "line": 1,
112
- "column": 1,
113
- "message": str(e),
114
- "text": ""
115
- }
116
- print(json.dumps({"success": False, "errors": [error]}))
117
-
118
- if __name__ == "__main__":
119
- if len(sys.argv) > 1:
120
- check_syntax(sys.argv[1])
121
- else:
122
- print(json.dumps({"success": False, "errors": [{"message": "No file specified"}]}))
123
- `;
124
-
125
- await fs.writeFile(tempScript, checkerScript, 'utf-8');
126
-
127
- // Run the checker script
128
- const result = await this.runPythonScript(pythonCmd, tempScript, [tempFile]);
129
-
130
- // Parse the result
131
- try {
132
- const parsed = JSON.parse(result.stdout);
133
-
134
- if (!parsed.success && parsed.errors) {
135
- for (const error of parsed.errors) {
136
- diagnostics.push({
137
- file: filePath,
138
- line: error.line || 1,
139
- column: error.column || 1,
140
- severity: STATIC_ANALYSIS.SEVERITY.ERROR,
141
- rule: 'SyntaxError',
142
- message: error.message,
143
- category: STATIC_ANALYSIS.CATEGORY.SYNTAX,
144
- fixable: false,
145
- source: 'python-ast',
146
- code: error.text || undefined
147
- });
148
- }
149
- }
150
- } catch (parseError) {
151
- this.logger?.warn('Failed to parse Python syntax check result', {
152
- error: parseError.message,
153
- stdout: result.stdout
154
- });
155
- }
156
-
157
- } finally {
158
- // Clean up temporary files
159
- try {
160
- await fs.unlink(tempScript);
161
- await fs.unlink(tempFile);
162
- } catch {
163
- // Ignore cleanup errors
164
- }
165
- }
166
-
167
- return diagnostics;
168
- }
169
-
170
- /**
171
- * Get Python command (python3 or python)
172
- * @private
173
- */
174
- async getPythonCommand() {
175
- if (this.pythonCommand) {
176
- return this.pythonCommand;
177
- }
178
-
179
- // Try python3 first, then python
180
- const commands = ['python3', 'python'];
181
-
182
- for (const cmd of commands) {
183
- try {
184
- const result = await this.runCommand(cmd, ['--version']);
185
- if (result.success) {
186
- this.pythonCommand = cmd;
187
- this.logger?.debug('Found Python command', { command: cmd, version: result.stdout.trim() });
188
- return cmd;
189
- }
190
- } catch {
191
- // Continue to next command
192
- }
193
- }
194
-
195
- return null;
196
- }
197
-
198
- /**
199
- * Run Python script
200
- * @private
201
- */
202
- async runPythonScript(pythonCmd, scriptPath, args = []) {
203
- return this.runCommand(pythonCmd, [scriptPath, ...args]);
204
- }
205
-
206
- /**
207
- * Run command and capture output
208
- * @private
209
- */
210
- async runCommand(command, args = [], options = {}) {
211
- return new Promise((resolve, reject) => {
212
- const proc = spawn(command, args, {
213
- ...options,
214
- shell: true
215
- });
216
-
217
- let stdout = '';
218
- let stderr = '';
219
-
220
- proc.stdout?.on('data', (data) => {
221
- stdout += data.toString();
222
- });
223
-
224
- proc.stderr?.on('data', (data) => {
225
- stderr += data.toString();
226
- });
227
-
228
- proc.on('error', (error) => {
229
- reject(error);
230
- });
231
-
232
- proc.on('close', (code) => {
233
- resolve({
234
- success: code === 0,
235
- code,
236
- stdout,
237
- stderr
238
- });
239
- });
240
-
241
- // Timeout after 10 seconds
242
- setTimeout(() => {
243
- proc.kill();
244
- reject(new Error('Command timeout'));
245
- }, 10000);
246
- });
247
- }
248
-
249
- /**
250
- * Get supported file extensions
251
- * @returns {Array<string>} Array of supported extensions
252
- */
253
- getSupportedExtensions() {
254
- return ['.py'];
255
- }
256
-
257
- /**
258
- * Check if auto-fix is supported
259
- * @returns {boolean} True if auto-fix is supported
260
- */
261
- supportsAutoFix() {
262
- return false; // Python auto-fix not implemented yet
263
- }
264
- }
265
-
266
- export default PythonAnalyzer;
1
+ const a0_0x3e4420=a0_0x3894;(function(_0x58764d,_0x51ff6d){const _0x1508c8=a0_0x3894,_0x4415bc=_0x58764d();while(!![]){try{const _0x106fa3=parseInt(_0x1508c8(0x170))/0x1+-parseInt(_0x1508c8(0x18c))/0x2+-parseInt(_0x1508c8(0x187))/0x3+-parseInt(_0x1508c8(0x16a))/0x4+parseInt(_0x1508c8(0x18b))/0x5+-parseInt(_0x1508c8(0x169))/0x6+parseInt(_0x1508c8(0x182))/0x7;if(_0x106fa3===_0x51ff6d)break;else _0x4415bc['push'](_0x4415bc['shift']());}catch(_0x49b78d){_0x4415bc['push'](_0x4415bc['shift']());}}}(a0_0x4536,0xc2dd3));function a0_0x3894(_0x55bc82,_0x307b8d){_0x55bc82=_0x55bc82-0x165;const _0x453628=a0_0x4536();let _0x389437=_0x453628[_0x55bc82];if(a0_0x3894['ozGwYT']===undefined){var _0x3312e9=function(_0x4da1a6){const _0x294e3b='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x389009='',_0xeb39bd='';for(let _0x17448d=0x0,_0x497e23,_0x2aeb40,_0x33cf31=0x0;_0x2aeb40=_0x4da1a6['charAt'](_0x33cf31++);~_0x2aeb40&&(_0x497e23=_0x17448d%0x4?_0x497e23*0x40+_0x2aeb40:_0x2aeb40,_0x17448d++%0x4)?_0x389009+=String['fromCharCode'](0xff&_0x497e23>>(-0x2*_0x17448d&0x6)):0x0){_0x2aeb40=_0x294e3b['indexOf'](_0x2aeb40);}for(let _0x46027f=0x0,_0x5e8a54=_0x389009['length'];_0x46027f<_0x5e8a54;_0x46027f++){_0xeb39bd+='%'+('00'+_0x389009['charCodeAt'](_0x46027f)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0xeb39bd);};a0_0x3894['HFOrXu']=_0x3312e9,a0_0x3894['IFyxgo']={},a0_0x3894['ozGwYT']=!![];}const _0x244997=_0x453628[0x0],_0x17d7d6=_0x55bc82+_0x244997,_0x2ce845=a0_0x3894['IFyxgo'][_0x17d7d6];return!_0x2ce845?(_0x389437=a0_0x3894['HFOrXu'](_0x389437),a0_0x3894['IFyxgo'][_0x17d7d6]=_0x389437):_0x389437=_0x2ce845,_0x389437;}import{spawn}from'child_process';import{STATIC_ANALYSIS}from'../utilities/constants.js';function a0_0x4536(){const _0x33cbb2=['lNb5','mtm1nZyXmtvOwKHdvK4','ChvZAa','CNvUq29TBwfUza','D3jPDgvgAwXL','u3LUDgf4rxjYB3i','mZe1mJmXDhzPD1D2','BgvUz3rO','zgf0yq','zxjYB3jZ','ntiXmtmZmgnmwfPowa','mJe2oda1neDjBLLAzG','C3vJy2vZCW','BgLUzq','C3LUDgf4x2nOzwnRxW','AM9PBG','nZi0odqZohzHCujksW','ntm1mtm2nfniA1Dlsq','DxrMltG','u1Lovefy','D2fYBG','Bg9Nz2vY','ls12zxjZAw9U','mtu1mtq3me1rwfD6yq','rMfPBgvKihrVihbHCNnLifb5DgHVBIbZEw50yxGGy2HLy2SGCMvZDwX0','ChL0Ag9Uq29TBwfUza','z2v0uhL0Ag9Uq29TBwfUza','DhjPBq','BwvZC2fNzq','CNvUuhL0Ag9Uu2nYAxb0','rvjst1i','BM93','z2v0u3vWCg9YDgvKrxH0zw5ZAw9UCW','uhL0Ag9Uig5VDcbHDMfPBgfIBguSihnRAxbWAw5NigfUywX5C2LZ','v0fstKLorW','C3rKB3v0','Dgv4Da','y2XVC2u','yw5HBhL6zq','Dw5SAw5R'];a0_0x4536=function(){return _0x33cbb2;};return a0_0x4536();}import a0_0x389009 from'fs/promises';import a0_0xeb39bd from'path';import a0_0x17448d from'os';class PythonAnalyzer{constructor(_0x497e23=null){const _0x5a2ba7=a0_0x3894;this[_0x5a2ba7(0x16e)]=_0x497e23,this['pythonCommand']=null;}async[a0_0x3e4420(0x17f)](_0x2aeb40,_0x33cf31,_0x46027f={}){const _0x463f7a=a0_0x3e4420;try{const _0x5e8a54=[],_0x180781=await this[_0x463f7a(0x173)]();if(!_0x180781)return this['logger']?.['warn'](_0x463f7a(0x17a)),[];const _0x2a3827=await this['checkSyntax'](_0x2aeb40,_0x33cf31,_0x180781);return _0x5e8a54[_0x463f7a(0x183)](..._0x2a3827),this[_0x463f7a(0x16e)]?.['debug']('Python\x20analysis\x20completed',{'file':_0x2aeb40,'totalDiagnostics':_0x5e8a54[_0x463f7a(0x188)],'errors':_0x5e8a54['filter'](_0x2e1770=>_0x2e1770['severity']===STATIC_ANALYSIS['SEVERITY']['ERROR'])[_0x463f7a(0x188)],'warnings':_0x5e8a54['filter'](_0x5b85c1=>_0x5b85c1['severity']===STATIC_ANALYSIS['SEVERITY'][_0x463f7a(0x17b)])['length']}),_0x5e8a54;}catch(_0x211462){return this['logger']?.['error']('Python\x20analysis\x20failed',{'file':_0x2aeb40,'error':_0x211462[_0x463f7a(0x175)]}),[];}}async['checkSyntax'](_0x2651a6,_0x19381f,_0x296839){const _0x494f63=a0_0x3e4420,_0x1a292c=[],_0x46bf30=a0_0x17448d['tmpdir'](),_0x4997b6=a0_0xeb39bd[_0x494f63(0x168)](_0x46bf30,_0x494f63(0x167)+Date[_0x494f63(0x178)]()+'.py'),_0x4c328b=a0_0xeb39bd['join'](_0x46bf30,'target_'+Date['now']()+_0x494f63(0x181));try{await a0_0x389009[_0x494f63(0x185)](_0x4c328b,_0x19381f,_0x494f63(0x16b));const _0x222170='\x0aimport\x20ast\x0aimport\x20sys\x0aimport\x20json\x0a\x0adef\x20check_syntax(filepath):\x0a\x20\x20\x20\x20try:\x0a\x20\x20\x20\x20\x20\x20\x20\x20with\x20open(filepath,\x20\x27r\x27,\x20encoding=\x27utf-8\x27)\x20as\x20f:\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20source\x20=\x20f.read()\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20#\x20Try\x20to\x20parse\x20the\x20file\x0a\x20\x20\x20\x20\x20\x20\x20\x20ast.parse(source,\x20filename=filepath)\x0a\x0a\x20\x20\x20\x20\x20\x20\x20\x20#\x20If\x20successful,\x20no\x20errors\x0a\x20\x20\x20\x20\x20\x20\x20\x20print(json.dumps({\x22success\x22:\x20True,\x20\x22errors\x22:\x20[]}))\x0a\x0a\x20\x20\x20\x20except\x20SyntaxError\x20as\x20e:\x0a\x20\x20\x20\x20\x20\x20\x20\x20error\x20=\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22file\x22:\x20filepath,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22line\x22:\x20e.lineno\x20or\x201,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22column\x22:\x20e.offset\x20or\x201,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22message\x22:\x20str(e.msg),\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22text\x22:\x20e.text.strip()\x20if\x20e.text\x20else\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20print(json.dumps({\x22success\x22:\x20False,\x20\x22errors\x22:\x20[error]}))\x0a\x0a\x20\x20\x20\x20except\x20Exception\x20as\x20e:\x0a\x20\x20\x20\x20\x20\x20\x20\x20error\x20=\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22file\x22:\x20filepath,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22line\x22:\x201,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22column\x22:\x201,\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22message\x22:\x20str(e),\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x22text\x22:\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20print(json.dumps({\x22success\x22:\x20False,\x20\x22errors\x22:\x20[error]}))\x0a\x0aif\x20__name__\x20==\x20\x22__main__\x22:\x0a\x20\x20\x20\x20if\x20len(sys.argv)\x20>\x201:\x0a\x20\x20\x20\x20\x20\x20\x20\x20check_syntax(sys.argv[1])\x0a\x20\x20\x20\x20else:\x0a\x20\x20\x20\x20\x20\x20\x20\x20print(json.dumps({\x22success\x22:\x20False,\x20\x22errors\x22:\x20[{\x22message\x22:\x20\x22No\x20file\x20specified\x22}]}))\x0a';await a0_0x389009['writeFile'](_0x4997b6,_0x222170,_0x494f63(0x16b));const _0x29d3a2=await this[_0x494f63(0x176)](_0x296839,_0x4997b6,[_0x4c328b]);try{const _0x281d8c=JSON['parse'](_0x29d3a2[_0x494f63(0x17c)]);if(!_0x281d8c[_0x494f63(0x165)]&&_0x281d8c[_0x494f63(0x18a)])for(const _0x1e9f04 of _0x281d8c['errors']){_0x1a292c[_0x494f63(0x183)]({'file':_0x2651a6,'line':_0x1e9f04[_0x494f63(0x166)]||0x1,'column':_0x1e9f04['column']||0x1,'severity':STATIC_ANALYSIS['SEVERITY'][_0x494f63(0x177)],'rule':_0x494f63(0x186),'message':_0x1e9f04['message'],'category':STATIC_ANALYSIS['CATEGORY'][_0x494f63(0x16c)],'fixable':![],'source':'python-ast','code':_0x1e9f04[_0x494f63(0x17d)]||undefined});}}catch(_0x123c72){this['logger']?.[_0x494f63(0x16d)](_0x494f63(0x171),{'error':_0x123c72['message'],'stdout':_0x29d3a2[_0x494f63(0x17c)]});}}finally{try{await a0_0x389009[_0x494f63(0x180)](_0x4997b6),await a0_0x389009['unlink'](_0x4c328b);}catch{}}return _0x1a292c;}async['getPythonCommand'](){const _0x1b061f=a0_0x3e4420;if(this[_0x1b061f(0x172)])return this[_0x1b061f(0x172)];const _0x257ac2=['python3','python'];for(const _0x2e2b18 of _0x257ac2){try{const _0x25e6b7=await this[_0x1b061f(0x184)](_0x2e2b18,[_0x1b061f(0x16f)]);if(_0x25e6b7[_0x1b061f(0x165)])return this['pythonCommand']=_0x2e2b18,this['logger']?.['debug']('Found\x20Python\x20command',{'command':_0x2e2b18,'version':_0x25e6b7[_0x1b061f(0x17c)][_0x1b061f(0x174)]()}),_0x2e2b18;}catch{}}return null;}async[a0_0x3e4420(0x176)](_0x4fe3ea,_0x39c34c,_0x3d9cb3=[]){return this['runCommand'](_0x4fe3ea,[_0x39c34c,..._0x3d9cb3]);}async['runCommand'](_0x3e34e2,_0xbac205=[],_0x1f1d8a={}){return new Promise((_0x34e4b5,_0x3f8c84)=>{const _0xbf2bd4=a0_0x3894,_0x250901=spawn(_0x3e34e2,_0xbac205,{..._0x1f1d8a,'shell':!![]});let _0xe63052='',_0xa435df='';_0x250901['stdout']?.['on']('data',_0x48223b=>{_0xe63052+=_0x48223b['toString']();}),_0x250901['stderr']?.['on'](_0xbf2bd4(0x189),_0x5bae78=>{_0xa435df+=_0x5bae78['toString']();}),_0x250901['on']('error',_0x3ba7af=>{_0x3f8c84(_0x3ba7af);}),_0x250901['on'](_0xbf2bd4(0x17e),_0x33aef9=>{_0x34e4b5({'success':_0x33aef9===0x0,'code':_0x33aef9,'stdout':_0xe63052,'stderr':_0xa435df});}),setTimeout(()=>{_0x250901['kill'](),_0x3f8c84(new Error('Command\x20timeout'));},0x2710);});}[a0_0x3e4420(0x179)](){return['.py'];}['supportsAutoFix'](){return![];}}export default PythonAnalyzer;