auto-coder 0.1.375__py3-none-any.whl → 0.1.376__py3-none-any.whl

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.

Potentially problematic release.


This version of auto-coder might be problematic. Click here for more details.

Files changed (51) hide show
  1. {auto_coder-0.1.375.dist-info → auto_coder-0.1.376.dist-info}/METADATA +1 -1
  2. {auto_coder-0.1.375.dist-info → auto_coder-0.1.376.dist-info}/RECORD +17 -51
  3. autocoder/agent/base_agentic/base_agent.py +9 -8
  4. autocoder/auto_coder_rag.py +12 -0
  5. autocoder/models.py +2 -2
  6. autocoder/rag/cache/local_duckdb_storage_cache.py +63 -33
  7. autocoder/rag/conversation_to_queries.py +37 -5
  8. autocoder/rag/long_context_rag.py +161 -41
  9. autocoder/rag/tools/recall_tool.py +2 -1
  10. autocoder/rag/tools/search_tool.py +2 -1
  11. autocoder/rag/types.py +36 -0
  12. autocoder/utils/_markitdown.py +59 -13
  13. autocoder/version.py +1 -1
  14. autocoder/agent/agentic_edit.py +0 -833
  15. autocoder/agent/agentic_edit_tools/__init__.py +0 -28
  16. autocoder/agent/agentic_edit_tools/ask_followup_question_tool_resolver.py +0 -32
  17. autocoder/agent/agentic_edit_tools/attempt_completion_tool_resolver.py +0 -29
  18. autocoder/agent/agentic_edit_tools/base_tool_resolver.py +0 -29
  19. autocoder/agent/agentic_edit_tools/execute_command_tool_resolver.py +0 -84
  20. autocoder/agent/agentic_edit_tools/list_code_definition_names_tool_resolver.py +0 -75
  21. autocoder/agent/agentic_edit_tools/list_files_tool_resolver.py +0 -62
  22. autocoder/agent/agentic_edit_tools/plan_mode_respond_tool_resolver.py +0 -30
  23. autocoder/agent/agentic_edit_tools/read_file_tool_resolver.py +0 -36
  24. autocoder/agent/agentic_edit_tools/replace_in_file_tool_resolver.py +0 -95
  25. autocoder/agent/agentic_edit_tools/search_files_tool_resolver.py +0 -70
  26. autocoder/agent/agentic_edit_tools/use_mcp_tool_resolver.py +0 -55
  27. autocoder/agent/agentic_edit_tools/write_to_file_tool_resolver.py +0 -98
  28. autocoder/agent/agentic_edit_types.py +0 -124
  29. autocoder/auto_coder_lang.py +0 -60
  30. autocoder/auto_coder_rag_client_mcp.py +0 -170
  31. autocoder/auto_coder_rag_mcp.py +0 -193
  32. autocoder/common/llm_rerank.py +0 -84
  33. autocoder/common/model_speed_test.py +0 -392
  34. autocoder/common/v2/agent/agentic_edit_conversation.py +0 -188
  35. autocoder/common/v2/agent/ignore_utils.py +0 -50
  36. autocoder/dispacher/actions/plugins/action_translate.py +0 -214
  37. autocoder/ignorefiles/__init__.py +0 -4
  38. autocoder/ignorefiles/ignore_file_utils.py +0 -63
  39. autocoder/ignorefiles/test_ignore_file_utils.py +0 -91
  40. autocoder/linters/code_linter.py +0 -588
  41. autocoder/rag/loaders/test_image_loader.py +0 -209
  42. autocoder/rag/raw_rag.py +0 -96
  43. autocoder/rag/simple_directory_reader.py +0 -646
  44. autocoder/rag/simple_rag.py +0 -404
  45. autocoder/regex_project/__init__.py +0 -162
  46. autocoder/utils/coder.py +0 -125
  47. autocoder/utils/tests.py +0 -37
  48. {auto_coder-0.1.375.dist-info → auto_coder-0.1.376.dist-info}/LICENSE +0 -0
  49. {auto_coder-0.1.375.dist-info → auto_coder-0.1.376.dist-info}/WHEEL +0 -0
  50. {auto_coder-0.1.375.dist-info → auto_coder-0.1.376.dist-info}/entry_points.txt +0 -0
  51. {auto_coder-0.1.375.dist-info → auto_coder-0.1.376.dist-info}/top_level.txt +0 -0
@@ -1,588 +0,0 @@
1
- """
2
- Module for linting frontend projects (ReactJS and Vue).
3
- This module provides functionality to analyze ReactJS and Vue projects for code quality and best practices.
4
- """
5
-
6
- import os
7
- import json
8
- import subprocess
9
- from typing import Dict, List, Optional, Union, Tuple, Any
10
-
11
- from autocoder.linters.base_linter import BaseLinter
12
-
13
- class FrontendLinter(BaseLinter):
14
- """
15
- A class that provides linting functionality for ReactJS and Vue projects and single files.
16
- """
17
-
18
- def __init__(self, verbose: bool = False):
19
- """
20
- Initialize the FrontendLinter.
21
-
22
- Args:
23
- verbose (bool): Whether to display verbose output.
24
- """
25
- super().__init__(verbose)
26
-
27
- def _check_dependencies(self) -> bool:
28
- """
29
- Check if required dependencies (node, npm, npx) are installed.
30
-
31
- Returns:
32
- bool: True if all dependencies are available, False otherwise.
33
- """
34
- try:
35
- # Check if node and npm are installed
36
- subprocess.run(["node", "--version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
37
- subprocess.run(["npm", "--version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
38
- subprocess.run(["npx", "--version"], check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
39
- return True
40
- except (subprocess.SubprocessError, FileNotFoundError):
41
- return False
42
-
43
- def get_supported_extensions(self) -> List[str]:
44
- """
45
- Get the list of file extensions supported by this linter.
46
-
47
- Returns:
48
- List[str]: List of supported file extensions.
49
- """
50
- return ['.js', '.jsx', '.ts', '.tsx', '.vue']
51
-
52
- def _detect_project_type(self, project_path: str) -> str:
53
- """
54
- Detect whether the project is ReactJS or Vue.
55
-
56
- Args:
57
- project_path (str): Path to the project directory.
58
-
59
- Returns:
60
- str: 'react', 'vue', or 'unknown'
61
- """
62
- # Check for package.json
63
- package_json_path = os.path.join(project_path, 'package.json')
64
- if not os.path.exists(package_json_path):
65
- return 'unknown'
66
-
67
- try:
68
- with open(package_json_path, 'r') as f:
69
- package_data = json.load(f)
70
-
71
- dependencies = {
72
- **package_data.get('dependencies', {}),
73
- **package_data.get('devDependencies', {})
74
- }
75
-
76
- # Check for React
77
- if 'react' in dependencies:
78
- return 'react'
79
-
80
- # Check for Vue
81
- if 'vue' in dependencies:
82
- return 'vue'
83
-
84
- return 'unknown'
85
- except (json.JSONDecodeError, FileNotFoundError):
86
- return 'unknown'
87
-
88
- def _detect_file_type(self, file_path: str) -> str:
89
- """
90
- Detect the type of file based on its extension.
91
-
92
- Args:
93
- file_path (str): Path to the file.
94
-
95
- Returns:
96
- str: 'react', 'vue', 'js', 'ts', or 'unknown'
97
- """
98
- if not os.path.exists(file_path) or not os.path.isfile(file_path):
99
- return 'unknown'
100
-
101
- # Get file extension
102
- ext = self.get_file_extension(file_path)
103
-
104
- if ext == '.jsx' or ext == '.tsx':
105
- return 'react'
106
- elif ext == '.vue':
107
- return 'vue'
108
- elif ext == '.js':
109
- # Check content for React imports
110
- try:
111
- with open(file_path, 'r', encoding='utf-8') as f:
112
- content = f.read()
113
- if 'import React' in content or 'from "react"' in content or "from 'react'" in content:
114
- return 'react'
115
- return 'js'
116
- except:
117
- return 'js'
118
- elif ext == '.ts':
119
- return 'ts'
120
- else:
121
- return 'unknown'
122
-
123
- def _install_eslint_if_needed(self, project_path: str, project_type: str) -> bool:
124
- """
125
- Install ESLint and the appropriate plugins if they're not already installed.
126
-
127
- Args:
128
- project_path (str): Path to the project directory.
129
- project_type (str): Type of the project ('react' or 'vue').
130
-
131
- Returns:
132
- bool: True if installation was successful, False otherwise.
133
- """
134
- try:
135
- # Check if .eslintrc.* exists
136
- eslint_configs = [
137
- os.path.join(project_path, '.eslintrc'),
138
- os.path.join(project_path, '.eslintrc.js'),
139
- os.path.join(project_path, '.eslintrc.json'),
140
- os.path.join(project_path, '.eslintrc.yml'),
141
- os.path.join(project_path, '.eslintrc.yaml')
142
- ]
143
-
144
- if any(os.path.exists(config) for config in eslint_configs):
145
- if self.verbose:
146
- print("ESLint configuration found.")
147
- return True
148
-
149
- # Install eslint and appropriate plugins
150
- if project_type == 'react':
151
- cmd = ["npm", "install", "--save-dev", "eslint", "eslint-plugin-react"]
152
- if self.verbose:
153
- print("Installing ESLint with React plugins...")
154
- elif project_type == 'vue':
155
- cmd = ["npm", "install", "--save-dev", "eslint", "eslint-plugin-vue"]
156
- if self.verbose:
157
- print("Installing ESLint with Vue plugins...")
158
- else:
159
- cmd = ["npm", "install", "--save-dev", "eslint"]
160
- if self.verbose:
161
- print("Installing ESLint...")
162
-
163
- result = subprocess.run(
164
- cmd,
165
- cwd=project_path,
166
- stdout=subprocess.PIPE if not self.verbose else None,
167
- stderr=subprocess.PIPE if not self.verbose else None
168
- )
169
-
170
- # Create basic configuration
171
- eslint_config = {
172
- "env": {
173
- "browser": True,
174
- "es2021": True,
175
- "node": True
176
- },
177
- "extends": ["eslint:recommended"]
178
- }
179
-
180
- if project_type == 'react':
181
- eslint_config["extends"].append("plugin:react/recommended")
182
- eslint_config["plugins"] = ["react"]
183
- eslint_config["parserOptions"] = {
184
- "ecmaFeatures": {
185
- "jsx": True
186
- },
187
- "ecmaVersion": 2021,
188
- "sourceType": "module"
189
- }
190
- elif project_type == 'vue':
191
- eslint_config["extends"].append("plugin:vue/vue3-recommended")
192
- eslint_config["plugins"] = ["vue"]
193
- eslint_config["parserOptions"] = {
194
- "ecmaVersion": 2021,
195
- "sourceType": "module"
196
- }
197
-
198
- # Write configuration
199
- with open(os.path.join(project_path, '.eslintrc.json'), 'w') as f:
200
- json.dump(eslint_config, f, indent=2)
201
-
202
- return result.returncode == 0
203
- except subprocess.SubprocessError:
204
- return False
205
-
206
- def lint_file(self, file_path: str, fix: bool = False, project_path: str = None) -> Dict[str, Any]:
207
- """
208
- Lint a single file using ESLint.
209
-
210
- Args:
211
- file_path (str): Path to the file to lint.
212
- fix (bool): Whether to automatically fix fixable issues.
213
- project_path (str, optional): Path to the project directory. If not provided,
214
- the parent directory of the file will be used.
215
-
216
- Returns:
217
- Dict: A dictionary containing lint results with the same structure as lint_project.
218
- """
219
- result = {
220
- 'success': False,
221
- 'file_type': 'unknown',
222
- 'files_analyzed': 0,
223
- 'error_count': 0,
224
- 'warning_count': 0,
225
- 'issues': []
226
- }
227
-
228
- # Check if file exists
229
- if not os.path.exists(file_path) or not os.path.isfile(file_path):
230
- result['error'] = f"File '{file_path}' does not exist or is not a file"
231
- return result
232
-
233
- # Check if file is supported
234
- if not self.is_supported_file(file_path):
235
- result['error'] = f"Unsupported file type for '{file_path}'"
236
- return result
237
-
238
- # Check dependencies
239
- if not self._check_dependencies():
240
- result['error'] = "Required dependencies (node, npm, npx) are not installed"
241
- return result
242
-
243
- # If project_path is not provided, use parent directory
244
- if project_path is None:
245
- project_path = os.path.dirname(file_path)
246
-
247
- # Detect file type
248
- file_type = self._detect_file_type(file_path)
249
- result['file_type'] = file_type
250
-
251
- if file_type == 'unknown':
252
- result['error'] = f"Unsupported file type for '{file_path}'"
253
- return result
254
-
255
- # Map file_type to project_type for ESLint setup
256
- project_type_map = {
257
- 'react': 'react',
258
- 'vue': 'vue',
259
- 'js': 'js',
260
- 'ts': 'js' # TypeScript uses generic JS ESLint with TS plugin
261
- }
262
- project_type = project_type_map.get(file_type, 'js')
263
-
264
- # Install ESLint if needed
265
- if not self._install_eslint_if_needed(project_path, project_type):
266
- result['error'] = "Failed to install or configure ESLint"
267
- return result
268
-
269
- # Run ESLint on the file
270
- try:
271
- cmd = ["npx", "eslint", "--format", "json"]
272
-
273
- # Add fix flag if requested
274
- if fix:
275
- cmd.append("--fix")
276
-
277
- # Add file path
278
- cmd.append(file_path)
279
-
280
- process = subprocess.run(
281
- cmd,
282
- cwd=project_path,
283
- stdout=subprocess.PIPE,
284
- stderr=subprocess.PIPE,
285
- text=True
286
- )
287
-
288
- # Parse ESLint output
289
- if process.stdout:
290
- try:
291
- eslint_output = json.loads(process.stdout)
292
-
293
- # Count files analyzed (should be 1)
294
- result['files_analyzed'] = len(eslint_output)
295
-
296
- # Track overall counts
297
- total_errors = 0
298
- total_warnings = 0
299
-
300
- # Process the file result
301
- for file_result in eslint_output:
302
- file_rel_path = os.path.relpath(file_result['filePath'], project_path)
303
-
304
- # Add error and warning counts
305
- total_errors += file_result.get('errorCount', 0)
306
- total_warnings += file_result.get('warningCount', 0)
307
-
308
- # Process individual messages
309
- for message in file_result.get('messages', []):
310
- issue = {
311
- 'file': file_rel_path,
312
- 'line': message.get('line', 0),
313
- 'column': message.get('column', 0),
314
- 'severity': 'error' if message.get('severity', 1) == 2 else 'warning',
315
- 'message': message.get('message', ''),
316
- 'rule': message.get('ruleId', 'unknown')
317
- }
318
- result['issues'].append(issue)
319
-
320
- result['error_count'] = total_errors
321
- result['warning_count'] = total_warnings
322
- result['success'] = True
323
- except json.JSONDecodeError:
324
- # Handle case where ESLint output is not valid JSON
325
- result['error'] = "Failed to parse ESLint output"
326
- else:
327
- # Handle case where ESLint didn't produce any output
328
- stderr = process.stderr.strip()
329
- if stderr:
330
- result['error'] = f"ESLint error: {stderr}"
331
- else:
332
- # No errors found
333
- result['success'] = True
334
- except subprocess.SubprocessError as e:
335
- result['error'] = f"Error running ESLint: {str(e)}"
336
-
337
- return result
338
-
339
- def lint_project(self, project_path: str, fix: bool = False) -> Dict[str, Any]:
340
- """
341
- Lint a ReactJS or Vue project.
342
-
343
- Args:
344
- project_path (str): Path to the project directory.
345
- fix (bool): Whether to automatically fix fixable issues.
346
-
347
- Returns:
348
- Dict: A dictionary containing lint results. Structure:
349
- {
350
- 'success': bool,
351
- 'project_type': str,
352
- 'files_analyzed': int,
353
- 'error_count': int,
354
- 'warning_count': int,
355
- 'issues': [
356
- {
357
- 'file': str,
358
- 'line': int,
359
- 'column': int,
360
- 'severity': str,
361
- 'message': str,
362
- 'rule': str
363
- },
364
- ...
365
- ]
366
- }
367
- """
368
- result = {
369
- 'success': False,
370
- 'project_type': 'unknown',
371
- 'files_analyzed': 0,
372
- 'error_count': 0,
373
- 'warning_count': 0,
374
- 'issues': []
375
- }
376
-
377
- # Check if the path exists
378
- if not os.path.exists(project_path) or not os.path.isdir(project_path):
379
- result['error'] = f"Path '{project_path}' does not exist or is not a directory"
380
- return result
381
-
382
- # Check dependencies
383
- if not self._check_dependencies():
384
- result['error'] = "Required dependencies (node, npm, npx) are not installed"
385
- return result
386
-
387
- # Detect project type
388
- project_type = self._detect_project_type(project_path)
389
- result['project_type'] = project_type
390
-
391
- if project_type == 'unknown':
392
- result['error'] = "Unable to detect project type (neither React nor Vue)"
393
- return result
394
-
395
- # Install ESLint if needed
396
- if not self._install_eslint_if_needed(project_path, project_type):
397
- result['error'] = "Failed to install or configure ESLint"
398
- return result
399
-
400
- # Run ESLint
401
- try:
402
- cmd = ["npx", "eslint", "--format", "json"]
403
-
404
- # Add fix flag if requested
405
- if fix:
406
- cmd.append("--fix")
407
-
408
- # Target directories based on project type
409
- if project_type == 'react':
410
- cmd.extend([
411
- "src/**/*.js",
412
- "src/**/*.jsx",
413
- "src/**/*.ts",
414
- "src/**/*.tsx"
415
- ])
416
- elif project_type == 'vue':
417
- cmd.extend([
418
- "src/**/*.js",
419
- "src/**/*.vue",
420
- "src/**/*.ts"
421
- ])
422
-
423
- process = subprocess.run(
424
- cmd,
425
- cwd=project_path,
426
- stdout=subprocess.PIPE,
427
- stderr=subprocess.PIPE,
428
- text=True
429
- )
430
-
431
- # Parse ESLint output
432
- if process.stdout:
433
- try:
434
- eslint_output = json.loads(process.stdout)
435
-
436
- # Count files analyzed
437
- result['files_analyzed'] = len(eslint_output)
438
-
439
- # Track overall counts
440
- total_errors = 0
441
- total_warnings = 0
442
-
443
- # Process each file result
444
- for file_result in eslint_output:
445
- file_path = os.path.relpath(file_result['filePath'], project_path)
446
-
447
- # Add error and warning counts
448
- total_errors += file_result.get('errorCount', 0)
449
- total_warnings += file_result.get('warningCount', 0)
450
-
451
- # Process individual messages
452
- for message in file_result.get('messages', []):
453
- issue = {
454
- 'file': file_path,
455
- 'line': message.get('line', 0),
456
- 'column': message.get('column', 0),
457
- 'severity': 'error' if message.get('severity', 1) == 2 else 'warning',
458
- 'message': message.get('message', ''),
459
- 'rule': message.get('ruleId', 'unknown')
460
- }
461
- result['issues'].append(issue)
462
-
463
- result['error_count'] = total_errors
464
- result['warning_count'] = total_warnings
465
- result['success'] = True
466
- except json.JSONDecodeError:
467
- # Handle case where ESLint output is not valid JSON
468
- result['error'] = "Failed to parse ESLint output"
469
- else:
470
- # Handle case where ESLint didn't produce any output
471
- stderr = process.stderr.strip()
472
- if stderr:
473
- result['error'] = f"ESLint error: {stderr}"
474
- else:
475
- # No errors found
476
- result['success'] = True
477
- except subprocess.SubprocessError as e:
478
- result['error'] = f"Error running ESLint: {str(e)}"
479
-
480
- return result
481
-
482
- def format_lint_result(self, lint_result: Dict[str, Any]) -> str:
483
- """
484
- Format lint results into a human-readable string.
485
-
486
- Args:
487
- lint_result (Dict): The lint result dictionary.
488
-
489
- Returns:
490
- str: A formatted string representation of the lint results.
491
- """
492
- if not lint_result.get('success', False):
493
- return f"Linting failed: {lint_result.get('error', 'Unknown error')}"
494
-
495
- # Handle both project_type and file_type
496
- if 'project_type' in lint_result:
497
- type_str = lint_result.get('project_type', 'unknown').capitalize()
498
- header = f"{type_str} Project Lint Results"
499
- else:
500
- type_str = lint_result.get('file_type', 'unknown').capitalize()
501
- header = f"{type_str} File Lint Results"
502
-
503
- files_analyzed = lint_result.get('files_analyzed', 0)
504
- error_count = lint_result.get('error_count', 0)
505
- warning_count = lint_result.get('warning_count', 0)
506
-
507
- output = [
508
- header,
509
- f"{'=' * 30}",
510
- f"Files analyzed: {files_analyzed}",
511
- f"Errors: {error_count}",
512
- f"Warnings: {warning_count}",
513
- ""
514
- ]
515
-
516
- if error_count == 0 and warning_count == 0:
517
- output.append("No issues found. Great job!")
518
- else:
519
- output.append("Issues:")
520
- output.append(f"{'-' * 30}")
521
-
522
- # Group issues by file
523
- issues_by_file = {}
524
- for issue in lint_result.get('issues', []):
525
- file_path = issue.get('file', '')
526
- if file_path not in issues_by_file:
527
- issues_by_file[file_path] = []
528
- issues_by_file[file_path].append(issue)
529
-
530
- # Display issues grouped by file
531
- for file_path, issues in issues_by_file.items():
532
- output.append(f"\nFile: {file_path}")
533
-
534
- for issue in issues:
535
- severity = issue.get('severity', '').upper()
536
- line = issue.get('line', 0)
537
- column = issue.get('column', 0)
538
- message = issue.get('message', '')
539
- rule = issue.get('rule', 'unknown')
540
-
541
- output.append(f" [{severity}] Line {line}, Col {column}: {message} ({rule})")
542
-
543
- return "\n".join(output)
544
-
545
- def lint_project(project_path: str, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
546
- """
547
- Utility function to lint a ReactJS or Vue project.
548
-
549
- Args:
550
- project_path (str): Path to the project directory.
551
- fix (bool): Whether to automatically fix fixable issues.
552
- verbose (bool): Whether to display verbose output.
553
-
554
- Returns:
555
- Dict: A dictionary containing lint results.
556
- """
557
- linter = FrontendLinter(verbose=verbose)
558
- return linter.lint_project(project_path, fix=fix)
559
-
560
- def lint_file(file_path: str, project_path: str = None, fix: bool = False, verbose: bool = False) -> Dict[str, Any]:
561
- """
562
- Utility function to lint a single file.
563
-
564
- Args:
565
- file_path (str): Path to the file to lint.
566
- project_path (str, optional): Path to the project directory. If not provided,
567
- the parent directory of the file will be used.
568
- fix (bool): Whether to automatically fix fixable issues.
569
- verbose (bool): Whether to display verbose output.
570
-
571
- Returns:
572
- Dict: A dictionary containing lint results.
573
- """
574
- linter = FrontendLinter(verbose=verbose)
575
- return linter.lint_file(file_path, fix=fix, project_path=project_path)
576
-
577
- def format_lint_result(lint_result: Dict[str, Any]) -> str:
578
- """
579
- Format lint results into a human-readable string.
580
-
581
- Args:
582
- lint_result (Dict): The lint result dictionary.
583
-
584
- Returns:
585
- str: A formatted string representation of the lint results.
586
- """
587
- linter = FrontendLinter()
588
- return linter.format_lint_result(lint_result)