ai-coding-assistant 0.5.0__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.
Files changed (89) hide show
  1. ai_coding_assistant-0.5.0.dist-info/METADATA +226 -0
  2. ai_coding_assistant-0.5.0.dist-info/RECORD +89 -0
  3. ai_coding_assistant-0.5.0.dist-info/WHEEL +4 -0
  4. ai_coding_assistant-0.5.0.dist-info/entry_points.txt +3 -0
  5. ai_coding_assistant-0.5.0.dist-info/licenses/LICENSE +21 -0
  6. coding_assistant/__init__.py +3 -0
  7. coding_assistant/__main__.py +19 -0
  8. coding_assistant/cli/__init__.py +1 -0
  9. coding_assistant/cli/app.py +158 -0
  10. coding_assistant/cli/commands/__init__.py +19 -0
  11. coding_assistant/cli/commands/ask.py +178 -0
  12. coding_assistant/cli/commands/config.py +438 -0
  13. coding_assistant/cli/commands/diagram.py +267 -0
  14. coding_assistant/cli/commands/document.py +410 -0
  15. coding_assistant/cli/commands/explain.py +192 -0
  16. coding_assistant/cli/commands/fix.py +249 -0
  17. coding_assistant/cli/commands/index.py +162 -0
  18. coding_assistant/cli/commands/refactor.py +245 -0
  19. coding_assistant/cli/commands/search.py +182 -0
  20. coding_assistant/cli/commands/serve_docs.py +128 -0
  21. coding_assistant/cli/repl.py +381 -0
  22. coding_assistant/cli/theme.py +90 -0
  23. coding_assistant/codebase/__init__.py +1 -0
  24. coding_assistant/codebase/crawler.py +93 -0
  25. coding_assistant/codebase/parser.py +266 -0
  26. coding_assistant/config/__init__.py +25 -0
  27. coding_assistant/config/config_manager.py +615 -0
  28. coding_assistant/config/settings.py +82 -0
  29. coding_assistant/context/__init__.py +19 -0
  30. coding_assistant/context/chunker.py +443 -0
  31. coding_assistant/context/enhanced_retriever.py +322 -0
  32. coding_assistant/context/hybrid_search.py +311 -0
  33. coding_assistant/context/ranker.py +355 -0
  34. coding_assistant/context/retriever.py +119 -0
  35. coding_assistant/context/window.py +362 -0
  36. coding_assistant/documentation/__init__.py +23 -0
  37. coding_assistant/documentation/agents/__init__.py +27 -0
  38. coding_assistant/documentation/agents/coordinator.py +510 -0
  39. coding_assistant/documentation/agents/module_documenter.py +111 -0
  40. coding_assistant/documentation/agents/synthesizer.py +139 -0
  41. coding_assistant/documentation/agents/task_delegator.py +100 -0
  42. coding_assistant/documentation/decomposition/__init__.py +21 -0
  43. coding_assistant/documentation/decomposition/context_preserver.py +477 -0
  44. coding_assistant/documentation/decomposition/module_detector.py +302 -0
  45. coding_assistant/documentation/decomposition/partitioner.py +621 -0
  46. coding_assistant/documentation/generators/__init__.py +14 -0
  47. coding_assistant/documentation/generators/dataflow_generator.py +440 -0
  48. coding_assistant/documentation/generators/diagram_generator.py +511 -0
  49. coding_assistant/documentation/graph/__init__.py +13 -0
  50. coding_assistant/documentation/graph/dependency_builder.py +468 -0
  51. coding_assistant/documentation/graph/module_analyzer.py +475 -0
  52. coding_assistant/documentation/writers/__init__.py +11 -0
  53. coding_assistant/documentation/writers/markdown_writer.py +322 -0
  54. coding_assistant/embeddings/__init__.py +0 -0
  55. coding_assistant/embeddings/generator.py +89 -0
  56. coding_assistant/embeddings/store.py +187 -0
  57. coding_assistant/exceptions/__init__.py +50 -0
  58. coding_assistant/exceptions/base.py +110 -0
  59. coding_assistant/exceptions/llm.py +249 -0
  60. coding_assistant/exceptions/recovery.py +263 -0
  61. coding_assistant/exceptions/storage.py +213 -0
  62. coding_assistant/exceptions/validation.py +230 -0
  63. coding_assistant/llm/__init__.py +1 -0
  64. coding_assistant/llm/client.py +277 -0
  65. coding_assistant/llm/gemini_client.py +181 -0
  66. coding_assistant/llm/groq_client.py +160 -0
  67. coding_assistant/llm/prompts.py +98 -0
  68. coding_assistant/llm/together_client.py +160 -0
  69. coding_assistant/operations/__init__.py +13 -0
  70. coding_assistant/operations/differ.py +369 -0
  71. coding_assistant/operations/generator.py +347 -0
  72. coding_assistant/operations/linter.py +430 -0
  73. coding_assistant/operations/validator.py +406 -0
  74. coding_assistant/storage/__init__.py +9 -0
  75. coding_assistant/storage/database.py +363 -0
  76. coding_assistant/storage/session.py +231 -0
  77. coding_assistant/utils/__init__.py +31 -0
  78. coding_assistant/utils/cache.py +477 -0
  79. coding_assistant/utils/hardware.py +132 -0
  80. coding_assistant/utils/keystore.py +206 -0
  81. coding_assistant/utils/logger.py +32 -0
  82. coding_assistant/utils/progress.py +311 -0
  83. coding_assistant/validation/__init__.py +13 -0
  84. coding_assistant/validation/files.py +305 -0
  85. coding_assistant/validation/inputs.py +335 -0
  86. coding_assistant/validation/params.py +280 -0
  87. coding_assistant/validation/sanitizers.py +243 -0
  88. coding_assistant/vcs/__init__.py +5 -0
  89. coding_assistant/vcs/git.py +269 -0
@@ -0,0 +1,266 @@
1
+ """Code parser using tree-sitter for better code understanding."""
2
+ from pathlib import Path
3
+ from typing import List, Dict, Optional
4
+ import tree_sitter_python as tspython
5
+ from tree_sitter import Language, Parser, Node
6
+
7
+ # Optional language imports - gracefully handle missing languages
8
+ try:
9
+ import tree_sitter_javascript as tsjs
10
+ JAVASCRIPT_AVAILABLE = True
11
+ except ImportError:
12
+ JAVASCRIPT_AVAILABLE = False
13
+
14
+ try:
15
+ import tree_sitter_java as tsjava
16
+ JAVA_AVAILABLE = True
17
+ except ImportError:
18
+ JAVA_AVAILABLE = False
19
+
20
+
21
+ class CodeParser:
22
+ """Parse code files and extract structured information across multiple languages."""
23
+
24
+ def __init__(self):
25
+ """Initialize parsers for multiple programming languages."""
26
+ # Python (always available)
27
+ self.PY_LANGUAGE = Language(tspython.language())
28
+
29
+ # Initialize parsers dict
30
+ self.parsers = {
31
+ 'python': Parser(self.PY_LANGUAGE)
32
+ }
33
+
34
+ # JavaScript/TypeScript (optional)
35
+ if JAVASCRIPT_AVAILABLE:
36
+ self.JS_LANGUAGE = Language(tsjs.language())
37
+ self.parsers['javascript'] = Parser(self.JS_LANGUAGE)
38
+ self.parsers['typescript'] = Parser(self.JS_LANGUAGE)
39
+
40
+ # Java (optional)
41
+ if JAVA_AVAILABLE:
42
+ self.JAVA_LANGUAGE = Language(tsjava.language())
43
+ self.parsers['java'] = Parser(self.JAVA_LANGUAGE)
44
+
45
+ # Default parser for backward compatibility
46
+ self.parser = self.parsers['python']
47
+
48
+ def detect_language(self, file_path: str) -> str:
49
+ """
50
+ Detect programming language from file extension.
51
+
52
+ Args:
53
+ file_path: Path to the file
54
+
55
+ Returns:
56
+ Language name (python, javascript, typescript, java, etc.)
57
+ """
58
+ extension = Path(file_path).suffix.lower()
59
+
60
+ extension_map = {
61
+ '.py': 'python',
62
+ '.js': 'javascript',
63
+ '.jsx': 'javascript',
64
+ '.ts': 'typescript',
65
+ '.tsx': 'typescript',
66
+ '.java': 'java',
67
+ }
68
+
69
+ return extension_map.get(extension, 'python')
70
+
71
+ def parse_file(self, file_path: str, content: str, language: Optional[str] = None) -> Dict:
72
+ """
73
+ Parse a code file and extract functions, classes, and metadata.
74
+
75
+ Supports multiple languages: Python, JavaScript, TypeScript, Java.
76
+
77
+ Args:
78
+ file_path: Path to the file
79
+ content: File contents
80
+ language: Programming language (auto-detected if not provided)
81
+
82
+ Returns:
83
+ Dictionary with parsed information
84
+ """
85
+ # Detect language if not provided
86
+ if language is None:
87
+ language = self.detect_language(file_path)
88
+
89
+ # Get appropriate parser
90
+ parser = self.parsers.get(language, self.parser)
91
+
92
+ # Parse the content
93
+ tree = parser.parse(bytes(content, "utf8"))
94
+ root = tree.root_node
95
+
96
+ return {
97
+ 'file_path': file_path,
98
+ 'language': language,
99
+ 'functions': self._extract_functions(root, content, language),
100
+ 'classes': self._extract_classes(root, content, language),
101
+ 'imports': self._extract_imports(root, content, language),
102
+ 'chunks': self._create_chunks(root, content, file_path, language)
103
+ }
104
+
105
+ def _extract_functions(self, node: Node, content: str, language: str = 'python') -> List[Dict]:
106
+ """Extract all function definitions (language-aware)."""
107
+ functions = []
108
+
109
+ # Define function node types per language
110
+ function_types = {
111
+ 'python': ['function_definition'],
112
+ 'javascript': ['function_declaration', 'function', 'arrow_function', 'method_definition'],
113
+ 'typescript': ['function_declaration', 'function', 'arrow_function', 'method_definition'],
114
+ 'java': ['method_declaration']
115
+ }
116
+
117
+ target_types = function_types.get(language, ['function_definition'])
118
+
119
+ def traverse(n: Node):
120
+ if n.type in target_types:
121
+ name_node = n.child_by_field_name('name')
122
+ if name_node:
123
+ functions.append({
124
+ 'name': content[name_node.start_byte:name_node.end_byte],
125
+ 'start_line': n.start_point[0],
126
+ 'end_line': n.end_point[0],
127
+ 'code': content[n.start_byte:n.end_byte]
128
+ })
129
+ elif language in ['javascript', 'typescript'] and n.type == 'arrow_function':
130
+ # Arrow functions might not have a name node
131
+ # Try to get name from parent variable declaration
132
+ parent = n.parent
133
+ if parent and parent.type == 'variable_declarator':
134
+ name_node = parent.child_by_field_name('name')
135
+ if name_node:
136
+ functions.append({
137
+ 'name': content[name_node.start_byte:name_node.end_byte],
138
+ 'start_line': n.start_point[0],
139
+ 'end_line': n.end_point[0],
140
+ 'code': content[n.start_byte:n.end_byte]
141
+ })
142
+
143
+ for child in n.children:
144
+ traverse(child)
145
+
146
+ traverse(node)
147
+ return functions
148
+
149
+ def _extract_classes(self, node: Node, content: str, language: str = 'python') -> List[Dict]:
150
+ """Extract all class definitions (language-aware)."""
151
+ classes = []
152
+
153
+ # Define class node types per language
154
+ class_types = {
155
+ 'python': ['class_definition'],
156
+ 'javascript': ['class_declaration'],
157
+ 'typescript': ['class_declaration'],
158
+ 'java': ['class_declaration']
159
+ }
160
+
161
+ target_types = class_types.get(language, ['class_definition'])
162
+
163
+ def traverse(n: Node):
164
+ if n.type in target_types:
165
+ name_node = n.child_by_field_name('name')
166
+ if name_node:
167
+ classes.append({
168
+ 'name': content[name_node.start_byte:name_node.end_byte],
169
+ 'start_line': n.start_point[0],
170
+ 'end_line': n.end_point[0],
171
+ 'code': content[n.start_byte:n.end_byte]
172
+ })
173
+
174
+ for child in n.children:
175
+ traverse(child)
176
+
177
+ traverse(node)
178
+ return classes
179
+
180
+ def _extract_imports(self, node: Node, content: str, language: str = 'python') -> List[str]:
181
+ """Extract all import statements (language-aware)."""
182
+ imports = []
183
+
184
+ # Define import node types per language
185
+ import_types = {
186
+ 'python': ['import_statement', 'import_from_statement'],
187
+ 'javascript': ['import_statement'],
188
+ 'typescript': ['import_statement'],
189
+ 'java': ['import_declaration']
190
+ }
191
+
192
+ target_types = import_types.get(language, ['import_statement', 'import_from_statement'])
193
+
194
+ def traverse(n: Node):
195
+ if n.type in target_types:
196
+ imports.append(content[n.start_byte:n.end_byte])
197
+
198
+ for child in n.children:
199
+ traverse(child)
200
+
201
+ traverse(node)
202
+ return imports
203
+
204
+ def _create_chunks(self, node: Node, content: str, file_path: str, language: str = 'python') -> List[Dict]:
205
+ """
206
+ Create smart code chunks for embedding.
207
+
208
+ Strategy:
209
+ 1. Each function is a chunk
210
+ 2. Each class is a chunk
211
+ 3. File header (imports, module docstring) is a chunk
212
+ """
213
+ chunks = []
214
+
215
+ # Extract file header (imports + module docstring)
216
+ header_lines = []
217
+ lines = content.split('\n')
218
+
219
+ # Get module docstring if exists
220
+ if node.children and node.children[0].type == 'expression_statement':
221
+ first_expr = node.children[0]
222
+ if first_expr.children and first_expr.children[0].type == 'string':
223
+ header_lines.append(content[first_expr.start_byte:first_expr.end_byte])
224
+
225
+ # Get all imports
226
+ imports = self._extract_imports(node, content, language)
227
+ if imports:
228
+ header_lines.extend(imports)
229
+
230
+ if header_lines:
231
+ chunks.append({
232
+ 'type': 'header',
233
+ 'file_path': file_path,
234
+ 'content': '\n'.join(header_lines),
235
+ 'start_line': 0,
236
+ 'end_line': len(header_lines),
237
+ 'language': language
238
+ })
239
+
240
+ # Extract function chunks
241
+ functions = self._extract_functions(node, content, language)
242
+ for func in functions:
243
+ chunks.append({
244
+ 'type': 'function',
245
+ 'file_path': file_path,
246
+ 'name': func['name'],
247
+ 'content': func['code'],
248
+ 'start_line': func['start_line'],
249
+ 'end_line': func['end_line'],
250
+ 'language': language
251
+ })
252
+
253
+ # Extract class chunks
254
+ classes = self._extract_classes(node, content, language)
255
+ for cls in classes:
256
+ chunks.append({
257
+ 'type': 'class',
258
+ 'file_path': file_path,
259
+ 'name': cls['name'],
260
+ 'content': cls['code'],
261
+ 'start_line': cls['start_line'],
262
+ 'end_line': cls['end_line'],
263
+ 'language': language
264
+ })
265
+
266
+ return chunks
@@ -0,0 +1,25 @@
1
+ """Configuration module."""
2
+
3
+ from coding_assistant.config.config_manager import (
4
+ Config,
5
+ ConfigManager,
6
+ ProjectConfig,
7
+ LLMConfig,
8
+ EmbeddingConfig,
9
+ SearchConfig,
10
+ CacheConfig,
11
+ UIConfig,
12
+ StorageConfig
13
+ )
14
+
15
+ __all__ = [
16
+ 'Config',
17
+ 'ConfigManager',
18
+ 'ProjectConfig',
19
+ 'LLMConfig',
20
+ 'EmbeddingConfig',
21
+ 'SearchConfig',
22
+ 'CacheConfig',
23
+ 'UIConfig',
24
+ 'StorageConfig',
25
+ ]