cognify-code 0.2.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_code_assistant/__init__.py +14 -0
- ai_code_assistant/agent/__init__.py +63 -0
- ai_code_assistant/agent/code_agent.py +461 -0
- ai_code_assistant/agent/code_generator.py +388 -0
- ai_code_assistant/agent/code_reviewer.py +365 -0
- ai_code_assistant/agent/diff_engine.py +308 -0
- ai_code_assistant/agent/file_manager.py +300 -0
- ai_code_assistant/agent/intent_classifier.py +284 -0
- ai_code_assistant/chat/__init__.py +11 -0
- ai_code_assistant/chat/agent_session.py +156 -0
- ai_code_assistant/chat/session.py +165 -0
- ai_code_assistant/cli.py +1571 -0
- ai_code_assistant/config.py +149 -0
- ai_code_assistant/editor/__init__.py +8 -0
- ai_code_assistant/editor/diff_handler.py +270 -0
- ai_code_assistant/editor/file_editor.py +350 -0
- ai_code_assistant/editor/prompts.py +146 -0
- ai_code_assistant/generator/__init__.py +7 -0
- ai_code_assistant/generator/code_gen.py +265 -0
- ai_code_assistant/generator/prompts.py +114 -0
- ai_code_assistant/git/__init__.py +6 -0
- ai_code_assistant/git/commit_generator.py +130 -0
- ai_code_assistant/git/manager.py +203 -0
- ai_code_assistant/llm.py +111 -0
- ai_code_assistant/providers/__init__.py +23 -0
- ai_code_assistant/providers/base.py +124 -0
- ai_code_assistant/providers/cerebras.py +97 -0
- ai_code_assistant/providers/factory.py +148 -0
- ai_code_assistant/providers/google.py +103 -0
- ai_code_assistant/providers/groq.py +111 -0
- ai_code_assistant/providers/ollama.py +86 -0
- ai_code_assistant/providers/openai.py +114 -0
- ai_code_assistant/providers/openrouter.py +130 -0
- ai_code_assistant/py.typed +0 -0
- ai_code_assistant/refactor/__init__.py +20 -0
- ai_code_assistant/refactor/analyzer.py +189 -0
- ai_code_assistant/refactor/change_plan.py +172 -0
- ai_code_assistant/refactor/multi_file_editor.py +346 -0
- ai_code_assistant/refactor/prompts.py +175 -0
- ai_code_assistant/retrieval/__init__.py +19 -0
- ai_code_assistant/retrieval/chunker.py +215 -0
- ai_code_assistant/retrieval/indexer.py +236 -0
- ai_code_assistant/retrieval/search.py +239 -0
- ai_code_assistant/reviewer/__init__.py +7 -0
- ai_code_assistant/reviewer/analyzer.py +278 -0
- ai_code_assistant/reviewer/prompts.py +113 -0
- ai_code_assistant/utils/__init__.py +18 -0
- ai_code_assistant/utils/file_handler.py +155 -0
- ai_code_assistant/utils/formatters.py +259 -0
- cognify_code-0.2.0.dist-info/METADATA +383 -0
- cognify_code-0.2.0.dist-info/RECORD +55 -0
- cognify_code-0.2.0.dist-info/WHEEL +5 -0
- cognify_code-0.2.0.dist-info/entry_points.txt +3 -0
- cognify_code-0.2.0.dist-info/licenses/LICENSE +22 -0
- cognify_code-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"""Multi-file editor for coordinated refactoring operations."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
import shutil
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Dict, List, Optional, Tuple
|
|
8
|
+
|
|
9
|
+
from ai_code_assistant.config import Config, get_language_by_extension
|
|
10
|
+
from ai_code_assistant.llm import LLMManager
|
|
11
|
+
from ai_code_assistant.editor.diff_handler import DiffHandler
|
|
12
|
+
from ai_code_assistant.refactor.prompts import (
|
|
13
|
+
MULTI_FILE_EDIT_PROMPT,
|
|
14
|
+
RENAME_SYMBOL_PROMPT,
|
|
15
|
+
EXTRACT_TO_FILE_PROMPT,
|
|
16
|
+
)
|
|
17
|
+
from ai_code_assistant.refactor.change_plan import (
|
|
18
|
+
ChangePlan,
|
|
19
|
+
FileChange,
|
|
20
|
+
ChangeType,
|
|
21
|
+
RefactorResult,
|
|
22
|
+
)
|
|
23
|
+
from ai_code_assistant.refactor.analyzer import RefactorAnalyzer
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MultiFileEditor:
|
|
27
|
+
"""Editor for coordinated multi-file refactoring."""
|
|
28
|
+
|
|
29
|
+
def __init__(self, config: Config, llm_manager: LLMManager):
|
|
30
|
+
"""Initialize the multi-file editor.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
config: Application configuration
|
|
34
|
+
llm_manager: LLM manager for AI interactions
|
|
35
|
+
"""
|
|
36
|
+
self.config = config
|
|
37
|
+
self.llm = llm_manager
|
|
38
|
+
self.diff_handler = DiffHandler()
|
|
39
|
+
self.analyzer = RefactorAnalyzer(config, llm_manager)
|
|
40
|
+
|
|
41
|
+
def refactor(
|
|
42
|
+
self,
|
|
43
|
+
instruction: str,
|
|
44
|
+
files: List[Path],
|
|
45
|
+
dry_run: bool = False,
|
|
46
|
+
create_backup: bool = True,
|
|
47
|
+
) -> RefactorResult:
|
|
48
|
+
"""Perform multi-file refactoring.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
instruction: Refactoring instruction
|
|
52
|
+
files: List of files to potentially modify
|
|
53
|
+
dry_run: If True, don't apply changes
|
|
54
|
+
create_backup: If True, create backup before changes
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
RefactorResult with all changes
|
|
58
|
+
"""
|
|
59
|
+
# Analyze to create plan
|
|
60
|
+
plan = self.analyzer.analyze(instruction, files)
|
|
61
|
+
|
|
62
|
+
if not plan.changes:
|
|
63
|
+
return RefactorResult(
|
|
64
|
+
plan=plan,
|
|
65
|
+
error="No changes identified",
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Read current file contents
|
|
69
|
+
file_contents = self._read_files([Path(c.file_path) for c in plan.changes])
|
|
70
|
+
|
|
71
|
+
# Update plan with original content
|
|
72
|
+
for change in plan.changes:
|
|
73
|
+
if change.file_path in file_contents:
|
|
74
|
+
change.original_content = file_contents[change.file_path]
|
|
75
|
+
|
|
76
|
+
# Generate changes
|
|
77
|
+
result = self._generate_changes(plan, file_contents)
|
|
78
|
+
|
|
79
|
+
if result.error:
|
|
80
|
+
return result
|
|
81
|
+
|
|
82
|
+
# Apply changes if not dry run
|
|
83
|
+
if not dry_run:
|
|
84
|
+
backup_dir = None
|
|
85
|
+
if create_backup:
|
|
86
|
+
backup_dir = self._create_backup(plan)
|
|
87
|
+
result.backup_dir = str(backup_dir) if backup_dir else None
|
|
88
|
+
|
|
89
|
+
self._apply_changes(plan)
|
|
90
|
+
result.applied = True
|
|
91
|
+
|
|
92
|
+
return result
|
|
93
|
+
|
|
94
|
+
def rename_symbol(
|
|
95
|
+
self,
|
|
96
|
+
old_name: str,
|
|
97
|
+
new_name: str,
|
|
98
|
+
symbol_type: str,
|
|
99
|
+
files: List[Path],
|
|
100
|
+
dry_run: bool = False,
|
|
101
|
+
) -> RefactorResult:
|
|
102
|
+
"""Rename a symbol across multiple files.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
old_name: Current symbol name
|
|
106
|
+
new_name: New symbol name
|
|
107
|
+
symbol_type: Type of symbol (function, class, variable, etc.)
|
|
108
|
+
files: Files to search and modify
|
|
109
|
+
dry_run: If True, don't apply changes
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
RefactorResult with all changes
|
|
113
|
+
"""
|
|
114
|
+
# Read file contents
|
|
115
|
+
file_contents = self._read_files(files)
|
|
116
|
+
|
|
117
|
+
# Filter to files containing the symbol
|
|
118
|
+
relevant_files = {
|
|
119
|
+
path: content for path, content in file_contents.items()
|
|
120
|
+
if old_name in content
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if not relevant_files:
|
|
124
|
+
plan = ChangePlan(
|
|
125
|
+
instruction=f"Rename {symbol_type} '{old_name}' to '{new_name}'",
|
|
126
|
+
summary=f"Symbol '{old_name}' not found in any files",
|
|
127
|
+
changes=[],
|
|
128
|
+
)
|
|
129
|
+
return RefactorResult(plan=plan, error="Symbol not found")
|
|
130
|
+
|
|
131
|
+
# Create plan
|
|
132
|
+
plan = ChangePlan(
|
|
133
|
+
instruction=f"Rename {symbol_type} '{old_name}' to '{new_name}'",
|
|
134
|
+
summary=f"Renaming {symbol_type} across {len(relevant_files)} files",
|
|
135
|
+
changes=[
|
|
136
|
+
FileChange(
|
|
137
|
+
file_path=path,
|
|
138
|
+
change_type=ChangeType.MODIFY,
|
|
139
|
+
description=f"Rename '{old_name}' to '{new_name}'",
|
|
140
|
+
original_content=content,
|
|
141
|
+
)
|
|
142
|
+
for path, content in relevant_files.items()
|
|
143
|
+
],
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# Generate changes using LLM
|
|
147
|
+
formatted_contents = self._format_file_contents(relevant_files)
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
response = self.llm.invoke_with_template(
|
|
151
|
+
RENAME_SYMBOL_PROMPT,
|
|
152
|
+
old_name=old_name,
|
|
153
|
+
new_name=new_name,
|
|
154
|
+
symbol_type=symbol_type,
|
|
155
|
+
file_contents=formatted_contents,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
self._parse_multi_file_response(plan, response)
|
|
159
|
+
|
|
160
|
+
except Exception as e:
|
|
161
|
+
return RefactorResult(plan=plan, error=f"LLM error: {str(e)}")
|
|
162
|
+
|
|
163
|
+
# Apply if not dry run
|
|
164
|
+
if not dry_run:
|
|
165
|
+
self._apply_changes(plan)
|
|
166
|
+
return RefactorResult(plan=plan, applied=True)
|
|
167
|
+
|
|
168
|
+
return RefactorResult(plan=plan)
|
|
169
|
+
|
|
170
|
+
def _read_files(self, files: List[Path]) -> Dict[str, str]:
|
|
171
|
+
"""Read contents of files."""
|
|
172
|
+
contents = {}
|
|
173
|
+
for file_path in files:
|
|
174
|
+
if file_path.exists():
|
|
175
|
+
try:
|
|
176
|
+
contents[str(file_path)] = file_path.read_text(encoding="utf-8")
|
|
177
|
+
except Exception:
|
|
178
|
+
pass
|
|
179
|
+
return contents
|
|
180
|
+
|
|
181
|
+
def _format_file_contents(self, contents: Dict[str, str]) -> str:
|
|
182
|
+
"""Format file contents for prompt."""
|
|
183
|
+
parts = []
|
|
184
|
+
for file_path, content in contents.items():
|
|
185
|
+
lang = get_language_by_extension(self.config, Path(file_path)) or "text"
|
|
186
|
+
parts.append(f"### {file_path}\n```{lang}\n{content}\n```\n")
|
|
187
|
+
return "\n".join(parts)
|
|
188
|
+
|
|
189
|
+
def _generate_changes(
|
|
190
|
+
self,
|
|
191
|
+
plan: ChangePlan,
|
|
192
|
+
file_contents: Dict[str, str],
|
|
193
|
+
) -> RefactorResult:
|
|
194
|
+
"""Generate actual file changes using LLM.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
plan: The change plan
|
|
198
|
+
file_contents: Current file contents
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
RefactorResult with generated changes
|
|
202
|
+
"""
|
|
203
|
+
# Format change plan for prompt
|
|
204
|
+
change_plan_text = "\n".join([
|
|
205
|
+
f"- {c.file_path}: {c.description} ({c.change_type.value})"
|
|
206
|
+
for c in plan.changes
|
|
207
|
+
])
|
|
208
|
+
|
|
209
|
+
formatted_contents = self._format_file_contents(file_contents)
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
response = self.llm.invoke_with_template(
|
|
213
|
+
MULTI_FILE_EDIT_PROMPT,
|
|
214
|
+
instruction=plan.instruction,
|
|
215
|
+
change_plan=change_plan_text,
|
|
216
|
+
file_contents=formatted_contents,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
self._parse_multi_file_response(plan, response)
|
|
220
|
+
|
|
221
|
+
# Generate diffs for each change
|
|
222
|
+
for change in plan.changes:
|
|
223
|
+
if change.new_content and change.original_content:
|
|
224
|
+
change.diff = self.diff_handler.generate_diff(
|
|
225
|
+
original=change.original_content,
|
|
226
|
+
modified=change.new_content,
|
|
227
|
+
filename=change.file_path,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
return RefactorResult(plan=plan)
|
|
231
|
+
|
|
232
|
+
except Exception as e:
|
|
233
|
+
return RefactorResult(plan=plan, error=f"LLM error: {str(e)}")
|
|
234
|
+
|
|
235
|
+
def _parse_multi_file_response(self, plan: ChangePlan, response: str) -> None:
|
|
236
|
+
"""Parse LLM response containing multiple file contents.
|
|
237
|
+
|
|
238
|
+
Args:
|
|
239
|
+
plan: Change plan to update
|
|
240
|
+
response: LLM response with file contents
|
|
241
|
+
"""
|
|
242
|
+
# Pattern to match file sections
|
|
243
|
+
pattern = r"###\s*FILE:\s*([^\n]+)\s*\n```\w*\s*\n(.*?)```"
|
|
244
|
+
matches = re.findall(pattern, response, re.DOTALL)
|
|
245
|
+
|
|
246
|
+
# Map new content to changes
|
|
247
|
+
for file_path, content in matches:
|
|
248
|
+
file_path = file_path.strip()
|
|
249
|
+
content = content.strip()
|
|
250
|
+
|
|
251
|
+
# Find matching change in plan
|
|
252
|
+
for change in plan.changes:
|
|
253
|
+
if change.file_path == file_path or file_path.endswith(change.file_path):
|
|
254
|
+
change.new_content = content
|
|
255
|
+
break
|
|
256
|
+
|
|
257
|
+
def _create_backup(self, plan: ChangePlan) -> Optional[Path]:
|
|
258
|
+
"""Create backup of all files to be modified.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
plan: Change plan with files to backup
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
Path to backup directory or None
|
|
265
|
+
"""
|
|
266
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
267
|
+
backup_dir = Path(f".refactor_backup_{timestamp}")
|
|
268
|
+
|
|
269
|
+
try:
|
|
270
|
+
backup_dir.mkdir(exist_ok=True)
|
|
271
|
+
|
|
272
|
+
for change in plan.changes:
|
|
273
|
+
if change.change_type in (ChangeType.MODIFY, ChangeType.DELETE):
|
|
274
|
+
src = Path(change.file_path)
|
|
275
|
+
if src.exists():
|
|
276
|
+
# Preserve directory structure in backup
|
|
277
|
+
dest = backup_dir / change.file_path
|
|
278
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
279
|
+
shutil.copy2(src, dest)
|
|
280
|
+
|
|
281
|
+
return backup_dir
|
|
282
|
+
|
|
283
|
+
except Exception:
|
|
284
|
+
return None
|
|
285
|
+
|
|
286
|
+
def _apply_changes(self, plan: ChangePlan) -> None:
|
|
287
|
+
"""Apply all changes in the plan.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
plan: Change plan with changes to apply
|
|
291
|
+
"""
|
|
292
|
+
for change in plan.get_ordered_changes():
|
|
293
|
+
try:
|
|
294
|
+
path = Path(change.file_path)
|
|
295
|
+
|
|
296
|
+
if change.change_type == ChangeType.DELETE:
|
|
297
|
+
if path.exists():
|
|
298
|
+
path.unlink()
|
|
299
|
+
change.applied = True
|
|
300
|
+
|
|
301
|
+
elif change.change_type == ChangeType.CREATE:
|
|
302
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
303
|
+
path.write_text(change.new_content, encoding="utf-8")
|
|
304
|
+
change.applied = True
|
|
305
|
+
|
|
306
|
+
elif change.change_type == ChangeType.RENAME:
|
|
307
|
+
if path.exists() and change.new_path:
|
|
308
|
+
new_path = Path(change.new_path)
|
|
309
|
+
new_path.parent.mkdir(parents=True, exist_ok=True)
|
|
310
|
+
shutil.move(str(path), str(new_path))
|
|
311
|
+
change.applied = True
|
|
312
|
+
|
|
313
|
+
elif change.change_type == ChangeType.MODIFY:
|
|
314
|
+
if change.new_content:
|
|
315
|
+
path.write_text(change.new_content, encoding="utf-8")
|
|
316
|
+
change.applied = True
|
|
317
|
+
else:
|
|
318
|
+
change.error = "No new content generated"
|
|
319
|
+
|
|
320
|
+
except Exception as e:
|
|
321
|
+
change.error = str(e)
|
|
322
|
+
|
|
323
|
+
def restore_backup(self, backup_dir: Path) -> bool:
|
|
324
|
+
"""Restore files from backup.
|
|
325
|
+
|
|
326
|
+
Args:
|
|
327
|
+
backup_dir: Path to backup directory
|
|
328
|
+
|
|
329
|
+
Returns:
|
|
330
|
+
True if successful
|
|
331
|
+
"""
|
|
332
|
+
if not backup_dir.exists():
|
|
333
|
+
return False
|
|
334
|
+
|
|
335
|
+
try:
|
|
336
|
+
for backup_file in backup_dir.rglob("*"):
|
|
337
|
+
if backup_file.is_file():
|
|
338
|
+
# Get relative path from backup dir
|
|
339
|
+
rel_path = backup_file.relative_to(backup_dir)
|
|
340
|
+
dest = Path(rel_path)
|
|
341
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
342
|
+
shutil.copy2(backup_file, dest)
|
|
343
|
+
return True
|
|
344
|
+
except Exception:
|
|
345
|
+
return False
|
|
346
|
+
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"""Prompt templates for multi-file refactoring."""
|
|
2
|
+
|
|
3
|
+
from langchain_core.prompts import ChatPromptTemplate
|
|
4
|
+
|
|
5
|
+
# System prompt for analyzing refactoring scope
|
|
6
|
+
ANALYZE_REFACTOR_SYSTEM = """You are an expert code architect analyzing a codebase for refactoring.
|
|
7
|
+
|
|
8
|
+
Your task is to analyze the provided code files and determine what changes are needed to accomplish the refactoring goal.
|
|
9
|
+
|
|
10
|
+
For each file that needs changes, provide:
|
|
11
|
+
1. The file path
|
|
12
|
+
2. The type of change (modify, create, delete, rename)
|
|
13
|
+
3. A description of what changes are needed
|
|
14
|
+
4. The priority (high, medium, low)
|
|
15
|
+
5. Dependencies on other file changes
|
|
16
|
+
|
|
17
|
+
Return your analysis as JSON with this structure:
|
|
18
|
+
{
|
|
19
|
+
"summary": "Brief description of the refactoring plan",
|
|
20
|
+
"affected_files": [
|
|
21
|
+
{
|
|
22
|
+
"file_path": "path/to/file.py",
|
|
23
|
+
"change_type": "modify|create|delete|rename",
|
|
24
|
+
"description": "What changes are needed",
|
|
25
|
+
"priority": "high|medium|low",
|
|
26
|
+
"depends_on": ["other/file.py"]
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"risks": ["List of potential risks or breaking changes"],
|
|
30
|
+
"estimated_complexity": "low|medium|high"
|
|
31
|
+
}"""
|
|
32
|
+
|
|
33
|
+
ANALYZE_REFACTOR_PROMPT = ChatPromptTemplate.from_messages([
|
|
34
|
+
("system", ANALYZE_REFACTOR_SYSTEM),
|
|
35
|
+
("human", """Analyze the following codebase for this refactoring task:
|
|
36
|
+
|
|
37
|
+
**Refactoring Goal:** {instruction}
|
|
38
|
+
|
|
39
|
+
**Files in scope:**
|
|
40
|
+
{file_contents}
|
|
41
|
+
|
|
42
|
+
Analyze what changes are needed and return a JSON plan.""")
|
|
43
|
+
])
|
|
44
|
+
|
|
45
|
+
# System prompt for generating multi-file changes
|
|
46
|
+
MULTI_FILE_EDIT_SYSTEM = """You are an expert code refactoring assistant performing coordinated changes across multiple files.
|
|
47
|
+
|
|
48
|
+
When making changes:
|
|
49
|
+
1. Ensure consistency across all files
|
|
50
|
+
2. Update all imports and references
|
|
51
|
+
3. Maintain backward compatibility where possible
|
|
52
|
+
4. Follow existing code style and patterns
|
|
53
|
+
5. Add appropriate type hints and docstrings
|
|
54
|
+
|
|
55
|
+
For each file, return the COMPLETE modified content wrapped in a code block with the filename as a comment."""
|
|
56
|
+
|
|
57
|
+
MULTI_FILE_EDIT_PROMPT = ChatPromptTemplate.from_messages([
|
|
58
|
+
("system", MULTI_FILE_EDIT_SYSTEM),
|
|
59
|
+
("human", """Apply the following refactoring across these files:
|
|
60
|
+
|
|
61
|
+
**Refactoring Goal:** {instruction}
|
|
62
|
+
|
|
63
|
+
**Change Plan:**
|
|
64
|
+
{change_plan}
|
|
65
|
+
|
|
66
|
+
**Current File Contents:**
|
|
67
|
+
{file_contents}
|
|
68
|
+
|
|
69
|
+
For each file that needs changes, return the complete modified content in this format:
|
|
70
|
+
|
|
71
|
+
### FILE: path/to/file.py
|
|
72
|
+
```python
|
|
73
|
+
# complete file content here
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### FILE: path/to/another.py
|
|
77
|
+
```javascript
|
|
78
|
+
// complete file content here
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Return ALL files that need changes with their complete content.""")
|
|
82
|
+
])
|
|
83
|
+
|
|
84
|
+
# Prompt for renaming symbols across files
|
|
85
|
+
RENAME_SYMBOL_PROMPT = ChatPromptTemplate.from_messages([
|
|
86
|
+
("system", """You are an expert at renaming symbols across a codebase.
|
|
87
|
+
|
|
88
|
+
When renaming:
|
|
89
|
+
1. Update all occurrences of the symbol
|
|
90
|
+
2. Update imports and exports
|
|
91
|
+
3. Update docstrings and comments that reference the symbol
|
|
92
|
+
4. Preserve all other code exactly as-is
|
|
93
|
+
|
|
94
|
+
Return each modified file with its complete content."""),
|
|
95
|
+
("human", """Rename the symbol across these files:
|
|
96
|
+
|
|
97
|
+
**Old Name:** {old_name}
|
|
98
|
+
**New Name:** {new_name}
|
|
99
|
+
**Symbol Type:** {symbol_type}
|
|
100
|
+
|
|
101
|
+
**Files:**
|
|
102
|
+
{file_contents}
|
|
103
|
+
|
|
104
|
+
Return each modified file with complete content in this format:
|
|
105
|
+
|
|
106
|
+
### FILE: path/to/file.py
|
|
107
|
+
```python
|
|
108
|
+
# complete file content
|
|
109
|
+
```""")
|
|
110
|
+
])
|
|
111
|
+
|
|
112
|
+
# Prompt for extracting code to new file
|
|
113
|
+
EXTRACT_TO_FILE_PROMPT = ChatPromptTemplate.from_messages([
|
|
114
|
+
("system", """You are an expert at extracting code into separate modules.
|
|
115
|
+
|
|
116
|
+
When extracting:
|
|
117
|
+
1. Move the specified code to a new file
|
|
118
|
+
2. Add appropriate imports to the new file
|
|
119
|
+
3. Update the original file to import from the new location
|
|
120
|
+
4. Ensure all references are updated
|
|
121
|
+
|
|
122
|
+
Return both the new file and modified original file."""),
|
|
123
|
+
("human", """Extract code to a new file:
|
|
124
|
+
|
|
125
|
+
**What to Extract:** {instruction}
|
|
126
|
+
**New File Path:** {new_file_path}
|
|
127
|
+
|
|
128
|
+
**Original File ({original_file}):**
|
|
129
|
+
```{language}
|
|
130
|
+
{original_content}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Return both files with complete content:
|
|
134
|
+
|
|
135
|
+
### FILE: {new_file_path}
|
|
136
|
+
```{language}
|
|
137
|
+
# new file content
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### FILE: {original_file}
|
|
141
|
+
```{language}
|
|
142
|
+
# modified original file
|
|
143
|
+
```""")
|
|
144
|
+
])
|
|
145
|
+
|
|
146
|
+
# Prompt for adding feature across multiple files
|
|
147
|
+
ADD_FEATURE_MULTI_PROMPT = ChatPromptTemplate.from_messages([
|
|
148
|
+
("system", """You are an expert at adding features that span multiple files.
|
|
149
|
+
|
|
150
|
+
When adding features:
|
|
151
|
+
1. Follow existing patterns in the codebase
|
|
152
|
+
2. Add necessary imports
|
|
153
|
+
3. Update configuration if needed
|
|
154
|
+
4. Add appropriate tests structure
|
|
155
|
+
5. Maintain consistency with existing code style
|
|
156
|
+
|
|
157
|
+
Return all files that need to be created or modified."""),
|
|
158
|
+
("human", """Add the following feature across the codebase:
|
|
159
|
+
|
|
160
|
+
**Feature Description:** {instruction}
|
|
161
|
+
|
|
162
|
+
**Existing Files:**
|
|
163
|
+
{file_contents}
|
|
164
|
+
|
|
165
|
+
**Files to Create/Modify:**
|
|
166
|
+
{target_files}
|
|
167
|
+
|
|
168
|
+
Return all files with complete content in this format:
|
|
169
|
+
|
|
170
|
+
### FILE: path/to/file.py
|
|
171
|
+
```python
|
|
172
|
+
# complete file content
|
|
173
|
+
```""")
|
|
174
|
+
])
|
|
175
|
+
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Codebase retrieval module for semantic search.
|
|
3
|
+
|
|
4
|
+
This module provides functionality to:
|
|
5
|
+
- Index code files into a vector database
|
|
6
|
+
- Search for relevant code using natural language queries
|
|
7
|
+
- Watch for file changes and update the index
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .indexer import CodebaseIndexer
|
|
11
|
+
from .search import CodebaseSearch
|
|
12
|
+
from .chunker import CodeChunker
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"CodebaseIndexer",
|
|
16
|
+
"CodebaseSearch",
|
|
17
|
+
"CodeChunker",
|
|
18
|
+
]
|
|
19
|
+
|