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.
- ai_coding_assistant-0.5.0.dist-info/METADATA +226 -0
- ai_coding_assistant-0.5.0.dist-info/RECORD +89 -0
- ai_coding_assistant-0.5.0.dist-info/WHEEL +4 -0
- ai_coding_assistant-0.5.0.dist-info/entry_points.txt +3 -0
- ai_coding_assistant-0.5.0.dist-info/licenses/LICENSE +21 -0
- coding_assistant/__init__.py +3 -0
- coding_assistant/__main__.py +19 -0
- coding_assistant/cli/__init__.py +1 -0
- coding_assistant/cli/app.py +158 -0
- coding_assistant/cli/commands/__init__.py +19 -0
- coding_assistant/cli/commands/ask.py +178 -0
- coding_assistant/cli/commands/config.py +438 -0
- coding_assistant/cli/commands/diagram.py +267 -0
- coding_assistant/cli/commands/document.py +410 -0
- coding_assistant/cli/commands/explain.py +192 -0
- coding_assistant/cli/commands/fix.py +249 -0
- coding_assistant/cli/commands/index.py +162 -0
- coding_assistant/cli/commands/refactor.py +245 -0
- coding_assistant/cli/commands/search.py +182 -0
- coding_assistant/cli/commands/serve_docs.py +128 -0
- coding_assistant/cli/repl.py +381 -0
- coding_assistant/cli/theme.py +90 -0
- coding_assistant/codebase/__init__.py +1 -0
- coding_assistant/codebase/crawler.py +93 -0
- coding_assistant/codebase/parser.py +266 -0
- coding_assistant/config/__init__.py +25 -0
- coding_assistant/config/config_manager.py +615 -0
- coding_assistant/config/settings.py +82 -0
- coding_assistant/context/__init__.py +19 -0
- coding_assistant/context/chunker.py +443 -0
- coding_assistant/context/enhanced_retriever.py +322 -0
- coding_assistant/context/hybrid_search.py +311 -0
- coding_assistant/context/ranker.py +355 -0
- coding_assistant/context/retriever.py +119 -0
- coding_assistant/context/window.py +362 -0
- coding_assistant/documentation/__init__.py +23 -0
- coding_assistant/documentation/agents/__init__.py +27 -0
- coding_assistant/documentation/agents/coordinator.py +510 -0
- coding_assistant/documentation/agents/module_documenter.py +111 -0
- coding_assistant/documentation/agents/synthesizer.py +139 -0
- coding_assistant/documentation/agents/task_delegator.py +100 -0
- coding_assistant/documentation/decomposition/__init__.py +21 -0
- coding_assistant/documentation/decomposition/context_preserver.py +477 -0
- coding_assistant/documentation/decomposition/module_detector.py +302 -0
- coding_assistant/documentation/decomposition/partitioner.py +621 -0
- coding_assistant/documentation/generators/__init__.py +14 -0
- coding_assistant/documentation/generators/dataflow_generator.py +440 -0
- coding_assistant/documentation/generators/diagram_generator.py +511 -0
- coding_assistant/documentation/graph/__init__.py +13 -0
- coding_assistant/documentation/graph/dependency_builder.py +468 -0
- coding_assistant/documentation/graph/module_analyzer.py +475 -0
- coding_assistant/documentation/writers/__init__.py +11 -0
- coding_assistant/documentation/writers/markdown_writer.py +322 -0
- coding_assistant/embeddings/__init__.py +0 -0
- coding_assistant/embeddings/generator.py +89 -0
- coding_assistant/embeddings/store.py +187 -0
- coding_assistant/exceptions/__init__.py +50 -0
- coding_assistant/exceptions/base.py +110 -0
- coding_assistant/exceptions/llm.py +249 -0
- coding_assistant/exceptions/recovery.py +263 -0
- coding_assistant/exceptions/storage.py +213 -0
- coding_assistant/exceptions/validation.py +230 -0
- coding_assistant/llm/__init__.py +1 -0
- coding_assistant/llm/client.py +277 -0
- coding_assistant/llm/gemini_client.py +181 -0
- coding_assistant/llm/groq_client.py +160 -0
- coding_assistant/llm/prompts.py +98 -0
- coding_assistant/llm/together_client.py +160 -0
- coding_assistant/operations/__init__.py +13 -0
- coding_assistant/operations/differ.py +369 -0
- coding_assistant/operations/generator.py +347 -0
- coding_assistant/operations/linter.py +430 -0
- coding_assistant/operations/validator.py +406 -0
- coding_assistant/storage/__init__.py +9 -0
- coding_assistant/storage/database.py +363 -0
- coding_assistant/storage/session.py +231 -0
- coding_assistant/utils/__init__.py +31 -0
- coding_assistant/utils/cache.py +477 -0
- coding_assistant/utils/hardware.py +132 -0
- coding_assistant/utils/keystore.py +206 -0
- coding_assistant/utils/logger.py +32 -0
- coding_assistant/utils/progress.py +311 -0
- coding_assistant/validation/__init__.py +13 -0
- coding_assistant/validation/files.py +305 -0
- coding_assistant/validation/inputs.py +335 -0
- coding_assistant/validation/params.py +280 -0
- coding_assistant/validation/sanitizers.py +243 -0
- coding_assistant/vcs/__init__.py +5 -0
- coding_assistant/vcs/git.py +269 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""Storage and index-related exceptions."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from coding_assistant.exceptions.base import AssistantError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StorageError(AssistantError):
|
|
9
|
+
"""Base exception for storage-related errors."""
|
|
10
|
+
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
message: str,
|
|
14
|
+
recoverable: bool = True,
|
|
15
|
+
suggestion: Optional[str] = None,
|
|
16
|
+
**kwargs
|
|
17
|
+
):
|
|
18
|
+
super().__init__(
|
|
19
|
+
message=message,
|
|
20
|
+
recoverable=recoverable,
|
|
21
|
+
suggestion=suggestion,
|
|
22
|
+
error_code="STORAGE_ERROR",
|
|
23
|
+
**kwargs
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class IndexError(StorageError):
|
|
28
|
+
"""Base exception for index-related errors."""
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class IndexNotFoundError(IndexError):
|
|
33
|
+
"""
|
|
34
|
+
Codebase index not found.
|
|
35
|
+
|
|
36
|
+
Raised when trying to query/search before indexing.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, project_path: Optional[Path] = None):
|
|
40
|
+
"""
|
|
41
|
+
Initialize index not found error.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
project_path: Path to project
|
|
45
|
+
"""
|
|
46
|
+
message = "Codebase has not been indexed yet"
|
|
47
|
+
if project_path:
|
|
48
|
+
message += f" for project: {project_path}"
|
|
49
|
+
|
|
50
|
+
super().__init__(
|
|
51
|
+
message=message,
|
|
52
|
+
recoverable=True,
|
|
53
|
+
suggestion=(
|
|
54
|
+
"Index your codebase first:\n"
|
|
55
|
+
" assistant index\n"
|
|
56
|
+
"\n"
|
|
57
|
+
"Or specify max files:\n"
|
|
58
|
+
" assistant index --max-files 200"
|
|
59
|
+
),
|
|
60
|
+
details={'project_path': str(project_path) if project_path else None}
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class IndexCorruptedError(IndexError):
|
|
65
|
+
"""
|
|
66
|
+
Index is corrupted or unreadable.
|
|
67
|
+
|
|
68
|
+
Raised when index exists but cannot be loaded.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
def __init__(self, reason: Optional[str] = None):
|
|
72
|
+
"""
|
|
73
|
+
Initialize index corrupted error.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
reason: Reason for corruption
|
|
77
|
+
"""
|
|
78
|
+
message = "Index is corrupted and cannot be loaded"
|
|
79
|
+
if reason:
|
|
80
|
+
message += f": {reason}"
|
|
81
|
+
|
|
82
|
+
super().__init__(
|
|
83
|
+
message=message,
|
|
84
|
+
recoverable=True,
|
|
85
|
+
suggestion=(
|
|
86
|
+
"Rebuild the index:\n"
|
|
87
|
+
" assistant index --force\n"
|
|
88
|
+
"\n"
|
|
89
|
+
"This will recreate the index from scratch."
|
|
90
|
+
),
|
|
91
|
+
details={'reason': reason}
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class IndexingError(IndexError):
|
|
96
|
+
"""
|
|
97
|
+
Error occurred during indexing.
|
|
98
|
+
|
|
99
|
+
Raised when indexing process fails.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(self, file_path: Optional[str] = None, reason: Optional[str] = None):
|
|
103
|
+
"""
|
|
104
|
+
Initialize indexing error.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
file_path: File being indexed when error occurred
|
|
108
|
+
reason: Reason for failure
|
|
109
|
+
"""
|
|
110
|
+
message = "Indexing failed"
|
|
111
|
+
if file_path:
|
|
112
|
+
message += f" while processing {file_path}"
|
|
113
|
+
if reason:
|
|
114
|
+
message += f": {reason}"
|
|
115
|
+
|
|
116
|
+
super().__init__(
|
|
117
|
+
message=message,
|
|
118
|
+
recoverable=True,
|
|
119
|
+
suggestion="Try indexing again or exclude problematic files",
|
|
120
|
+
details={
|
|
121
|
+
'file_path': file_path,
|
|
122
|
+
'reason': reason
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class SessionError(StorageError):
|
|
128
|
+
"""Base exception for session-related errors."""
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class SessionNotFoundError(SessionError):
|
|
133
|
+
"""
|
|
134
|
+
Session not found.
|
|
135
|
+
|
|
136
|
+
Raised when trying to access non-existent session.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def __init__(self, session_id: int):
|
|
140
|
+
"""
|
|
141
|
+
Initialize session not found error.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
session_id: Session ID
|
|
145
|
+
"""
|
|
146
|
+
super().__init__(
|
|
147
|
+
message=f"Session {session_id} not found",
|
|
148
|
+
recoverable=True,
|
|
149
|
+
suggestion="Check session ID or start a new session with 'assistant chat'",
|
|
150
|
+
details={'session_id': session_id}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class DatabaseError(StorageError):
|
|
155
|
+
"""
|
|
156
|
+
Database operation failed.
|
|
157
|
+
|
|
158
|
+
Raised when SQLite operations fail.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
def __init__(self, operation: str, reason: Optional[str] = None):
|
|
162
|
+
"""
|
|
163
|
+
Initialize database error.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
operation: Database operation being performed
|
|
167
|
+
reason: Reason for failure
|
|
168
|
+
"""
|
|
169
|
+
message = f"Database operation '{operation}' failed"
|
|
170
|
+
if reason:
|
|
171
|
+
message += f": {reason}"
|
|
172
|
+
|
|
173
|
+
super().__init__(
|
|
174
|
+
message=message,
|
|
175
|
+
recoverable=True,
|
|
176
|
+
suggestion="Check database permissions and disk space",
|
|
177
|
+
details={
|
|
178
|
+
'operation': operation,
|
|
179
|
+
'reason': reason
|
|
180
|
+
}
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class CacheError(StorageError):
|
|
185
|
+
"""
|
|
186
|
+
Cache operation failed.
|
|
187
|
+
|
|
188
|
+
Raised when cache read/write fails.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
def __init__(self, operation: str, cache_type: str, reason: Optional[str] = None):
|
|
192
|
+
"""
|
|
193
|
+
Initialize cache error.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
operation: Cache operation (get, set, delete)
|
|
197
|
+
cache_type: Type of cache (embedding, response)
|
|
198
|
+
reason: Reason for failure
|
|
199
|
+
"""
|
|
200
|
+
message = f"Cache {operation} failed for {cache_type} cache"
|
|
201
|
+
if reason:
|
|
202
|
+
message += f": {reason}"
|
|
203
|
+
|
|
204
|
+
super().__init__(
|
|
205
|
+
message=message,
|
|
206
|
+
recoverable=True, # Cache failures should not break functionality
|
|
207
|
+
suggestion="Cache will be bypassed. Clear cache if issues persist:\n rm -rf .assistant/cache",
|
|
208
|
+
details={
|
|
209
|
+
'operation': operation,
|
|
210
|
+
'cache_type': cache_type,
|
|
211
|
+
'reason': reason
|
|
212
|
+
}
|
|
213
|
+
)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"""Input validation exceptions."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from coding_assistant.exceptions.base import AssistantError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ValidationError(AssistantError):
|
|
9
|
+
"""
|
|
10
|
+
Base exception for validation errors.
|
|
11
|
+
|
|
12
|
+
Raised when user input is invalid.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
field: str,
|
|
18
|
+
reason: str,
|
|
19
|
+
value: Optional[str] = None,
|
|
20
|
+
suggestion: Optional[str] = None
|
|
21
|
+
):
|
|
22
|
+
"""
|
|
23
|
+
Initialize validation error.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
field: Field name that failed validation
|
|
27
|
+
reason: Reason for validation failure
|
|
28
|
+
value: Invalid value (optional)
|
|
29
|
+
suggestion: Suggestion for fixing
|
|
30
|
+
"""
|
|
31
|
+
message = f"Invalid {field}: {reason}"
|
|
32
|
+
|
|
33
|
+
if not suggestion:
|
|
34
|
+
suggestion = f"Please provide a valid {field}"
|
|
35
|
+
|
|
36
|
+
super().__init__(
|
|
37
|
+
message=message,
|
|
38
|
+
recoverable=True,
|
|
39
|
+
suggestion=suggestion,
|
|
40
|
+
error_code="VALIDATION_ERROR",
|
|
41
|
+
details={
|
|
42
|
+
'field': field,
|
|
43
|
+
'reason': reason,
|
|
44
|
+
'value': value
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class FileNotFoundError(ValidationError):
|
|
50
|
+
"""
|
|
51
|
+
File not found.
|
|
52
|
+
|
|
53
|
+
Raised when specified file does not exist.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
def __init__(self, file_path: Path):
|
|
57
|
+
"""
|
|
58
|
+
Initialize file not found error.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
file_path: Path to missing file
|
|
62
|
+
"""
|
|
63
|
+
super().__init__(
|
|
64
|
+
field="file path",
|
|
65
|
+
reason=f"File not found: {file_path}",
|
|
66
|
+
value=str(file_path),
|
|
67
|
+
suggestion=f"Check that the file exists:\n ls {file_path}"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class InvalidQueryError(ValidationError):
|
|
72
|
+
"""
|
|
73
|
+
Invalid search query.
|
|
74
|
+
|
|
75
|
+
Raised when search query is malformed or too short/long.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
def __init__(self, query: str, reason: str):
|
|
79
|
+
"""
|
|
80
|
+
Initialize invalid query error.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
query: Invalid query
|
|
84
|
+
reason: Reason for invalidity
|
|
85
|
+
"""
|
|
86
|
+
super().__init__(
|
|
87
|
+
field="query",
|
|
88
|
+
reason=reason,
|
|
89
|
+
value=query[:50] + "..." if len(query) > 50 else query,
|
|
90
|
+
suggestion="Provide a clear, specific query (3-500 characters)"
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class InvalidParameterError(ValidationError):
|
|
95
|
+
"""
|
|
96
|
+
Invalid parameter value.
|
|
97
|
+
|
|
98
|
+
Raised when command parameter is invalid.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def __init__(
|
|
102
|
+
self,
|
|
103
|
+
parameter: str,
|
|
104
|
+
value: any,
|
|
105
|
+
expected: str,
|
|
106
|
+
suggestion: Optional[str] = None
|
|
107
|
+
):
|
|
108
|
+
"""
|
|
109
|
+
Initialize invalid parameter error.
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
parameter: Parameter name
|
|
113
|
+
value: Invalid value
|
|
114
|
+
expected: Expected value description
|
|
115
|
+
suggestion: Optional suggestion
|
|
116
|
+
"""
|
|
117
|
+
super().__init__(
|
|
118
|
+
field=parameter,
|
|
119
|
+
reason=f"Expected {expected}, got {type(value).__name__}: {value}",
|
|
120
|
+
value=str(value),
|
|
121
|
+
suggestion=suggestion or f"Provide a valid {parameter} ({expected})"
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class EmptyInputError(ValidationError):
|
|
126
|
+
"""
|
|
127
|
+
Empty input provided.
|
|
128
|
+
|
|
129
|
+
Raised when required input is empty.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
def __init__(self, field: str):
|
|
133
|
+
"""
|
|
134
|
+
Initialize empty input error.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
field: Field name
|
|
138
|
+
"""
|
|
139
|
+
super().__init__(
|
|
140
|
+
field=field,
|
|
141
|
+
reason="Input cannot be empty",
|
|
142
|
+
value="",
|
|
143
|
+
suggestion=f"Provide a non-empty {field}"
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class PathSecurityError(ValidationError):
|
|
148
|
+
"""
|
|
149
|
+
Potentially dangerous file path.
|
|
150
|
+
|
|
151
|
+
Raised when path contains suspicious patterns.
|
|
152
|
+
"""
|
|
153
|
+
|
|
154
|
+
def __init__(self, file_path: Path, reason: str):
|
|
155
|
+
"""
|
|
156
|
+
Initialize path security error.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
file_path: Suspicious path
|
|
160
|
+
reason: Security concern
|
|
161
|
+
"""
|
|
162
|
+
super().__init__(
|
|
163
|
+
field="file path",
|
|
164
|
+
reason=f"Security concern: {reason}",
|
|
165
|
+
value=str(file_path),
|
|
166
|
+
suggestion="Use a safe, absolute path within your project"
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class CodeSyntaxError(ValidationError):
|
|
171
|
+
"""
|
|
172
|
+
Code has syntax errors.
|
|
173
|
+
|
|
174
|
+
Raised when generated/modified code is invalid.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
def __init__(
|
|
178
|
+
self,
|
|
179
|
+
file_path: Optional[str] = None,
|
|
180
|
+
line: Optional[int] = None,
|
|
181
|
+
message: Optional[str] = None
|
|
182
|
+
):
|
|
183
|
+
"""
|
|
184
|
+
Initialize code syntax error.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
file_path: File with syntax error
|
|
188
|
+
line: Line number
|
|
189
|
+
message: Error message from parser
|
|
190
|
+
"""
|
|
191
|
+
reason = "Code has syntax errors"
|
|
192
|
+
if file_path:
|
|
193
|
+
reason += f" in {file_path}"
|
|
194
|
+
if line:
|
|
195
|
+
reason += f" at line {line}"
|
|
196
|
+
if message:
|
|
197
|
+
reason += f": {message}"
|
|
198
|
+
|
|
199
|
+
super().__init__(
|
|
200
|
+
field="code",
|
|
201
|
+
reason=reason,
|
|
202
|
+
value=None,
|
|
203
|
+
suggestion="Fix syntax errors before applying changes"
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class ConfigurationError(ValidationError):
|
|
208
|
+
"""
|
|
209
|
+
Configuration is invalid.
|
|
210
|
+
|
|
211
|
+
Raised when config file has errors.
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
def __init__(self, config_file: Path, reason: str):
|
|
215
|
+
"""
|
|
216
|
+
Initialize configuration error.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
config_file: Configuration file path
|
|
220
|
+
reason: What's wrong with the config
|
|
221
|
+
"""
|
|
222
|
+
super().__init__(
|
|
223
|
+
field="configuration",
|
|
224
|
+
reason=reason,
|
|
225
|
+
value=str(config_file),
|
|
226
|
+
suggestion=(
|
|
227
|
+
"Fix configuration errors or regenerate default config:\n"
|
|
228
|
+
" assistant config --generate"
|
|
229
|
+
)
|
|
230
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""LLM integration module."""
|