codegraph-cli 2.0.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 (43) hide show
  1. codegraph_cli/__init__.py +4 -0
  2. codegraph_cli/agents.py +191 -0
  3. codegraph_cli/bug_detector.py +386 -0
  4. codegraph_cli/chat_agent.py +352 -0
  5. codegraph_cli/chat_session.py +220 -0
  6. codegraph_cli/cli.py +330 -0
  7. codegraph_cli/cli_chat.py +367 -0
  8. codegraph_cli/cli_diagnose.py +133 -0
  9. codegraph_cli/cli_refactor.py +230 -0
  10. codegraph_cli/cli_setup.py +470 -0
  11. codegraph_cli/cli_test.py +177 -0
  12. codegraph_cli/cli_v2.py +267 -0
  13. codegraph_cli/codegen_agent.py +265 -0
  14. codegraph_cli/config.py +31 -0
  15. codegraph_cli/config_manager.py +341 -0
  16. codegraph_cli/context_manager.py +500 -0
  17. codegraph_cli/crew_agents.py +123 -0
  18. codegraph_cli/crew_chat.py +159 -0
  19. codegraph_cli/crew_tools.py +497 -0
  20. codegraph_cli/diff_engine.py +265 -0
  21. codegraph_cli/embeddings.py +241 -0
  22. codegraph_cli/graph_export.py +144 -0
  23. codegraph_cli/llm.py +642 -0
  24. codegraph_cli/models.py +47 -0
  25. codegraph_cli/models_v2.py +185 -0
  26. codegraph_cli/orchestrator.py +49 -0
  27. codegraph_cli/parser.py +800 -0
  28. codegraph_cli/performance_analyzer.py +223 -0
  29. codegraph_cli/project_context.py +230 -0
  30. codegraph_cli/rag.py +200 -0
  31. codegraph_cli/refactor_agent.py +452 -0
  32. codegraph_cli/security_scanner.py +366 -0
  33. codegraph_cli/storage.py +390 -0
  34. codegraph_cli/templates/graph_interactive.html +257 -0
  35. codegraph_cli/testgen_agent.py +316 -0
  36. codegraph_cli/validation_engine.py +285 -0
  37. codegraph_cli/vector_store.py +293 -0
  38. codegraph_cli-2.0.0.dist-info/METADATA +318 -0
  39. codegraph_cli-2.0.0.dist-info/RECORD +43 -0
  40. codegraph_cli-2.0.0.dist-info/WHEEL +5 -0
  41. codegraph_cli-2.0.0.dist-info/entry_points.txt +2 -0
  42. codegraph_cli-2.0.0.dist-info/licenses/LICENSE +21 -0
  43. codegraph_cli-2.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,133 @@
1
+ """CLI commands for error detection and fixing."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ import typer
8
+
9
+ from .diff_engine import DiffEngine
10
+ from .models_v2 import CodeProposal
11
+ from .storage import ProjectManager
12
+ from .validation_engine import ValidationEngine
13
+
14
+ # Create sub-app for diagnostic commands
15
+ diagnose_app = typer.Typer(help="Detect and fix code errors")
16
+
17
+
18
+ @diagnose_app.command("check")
19
+ def check_errors(
20
+ path: str = typer.Argument(".", help="Path to check (default: current directory)"),
21
+ ):
22
+ """Scan project for syntax errors."""
23
+ project_path = Path(path).resolve()
24
+
25
+ if not project_path.exists():
26
+ typer.echo(f"āŒ Path not found: {path}")
27
+ raise typer.Exit(1)
28
+
29
+ typer.echo(f"šŸ” Scanning {project_path} for errors...")
30
+
31
+ validator = ValidationEngine()
32
+ errors = validator.diagnose_project(project_path)
33
+
34
+ if not errors:
35
+ typer.echo("āœ… No syntax errors found!")
36
+ return
37
+
38
+ typer.echo(f"\nšŸ“‹ Found {len(errors)} error(s):\n")
39
+
40
+ for i, error in enumerate(errors, 1):
41
+ typer.echo(f"{i}. {error['file']}:{error['line']}")
42
+ typer.echo(f" {error['type']}: {error['error']}")
43
+ typer.echo("")
44
+
45
+
46
+ @diagnose_app.command("fix")
47
+ def fix_errors(
48
+ path: str = typer.Argument(".", help="Path to fix (default: current directory)"),
49
+ preview_only: bool = typer.Option(False, "--preview", "-p", help="Preview fixes without applying"),
50
+ auto_apply: bool = typer.Option(False, "--auto-apply", "-y", help="Apply fixes without confirmation"),
51
+ ):
52
+ """Automatically fix common syntax errors."""
53
+ project_path = Path(path).resolve()
54
+
55
+ if not project_path.exists():
56
+ typer.echo(f"āŒ Path not found: {path}")
57
+ raise typer.Exit(1)
58
+
59
+ typer.echo(f"šŸ”§ Fixing errors in {project_path}...")
60
+
61
+ validator = ValidationEngine()
62
+ errors = validator.diagnose_project(project_path)
63
+
64
+ if not errors:
65
+ typer.echo("āœ… No errors to fix!")
66
+ return
67
+
68
+ typer.echo(f"\nšŸ“‹ Found {len(errors)} error(s), attempting fixes...\n")
69
+
70
+ # Try to fix each file
71
+ changes = []
72
+ for error in errors:
73
+ file_path = Path(error['file'])
74
+
75
+ typer.echo(f"šŸ”§ Fixing {file_path.name}:{error['line']}...")
76
+ typer.echo(f" Problem: {error['error']}")
77
+
78
+ fix = validator.fix_common_errors(file_path)
79
+
80
+ if fix:
81
+ changes.append(fix)
82
+ typer.echo(f" āœ… Fix applied")
83
+ else:
84
+ typer.echo(f" āš ļø Could not auto-fix (manual intervention needed)")
85
+ typer.echo("")
86
+
87
+ if not changes:
88
+ typer.echo("āŒ No automatic fixes available. Manual fixes required.")
89
+ return
90
+
91
+ # Show preview
92
+ diff_engine = DiffEngine()
93
+ proposal = CodeProposal(
94
+ id="fix-errors",
95
+ description=f"Fix {len(changes)} syntax error(s)",
96
+ changes=changes
97
+ )
98
+
99
+ typer.echo("="*60)
100
+ typer.echo("PROPOSED FIXES")
101
+ typer.echo("="*60)
102
+ preview = diff_engine.preview_changes(proposal)
103
+ typer.echo(preview)
104
+
105
+ if preview_only:
106
+ typer.echo("\nšŸ“‹ Preview only mode - no changes applied")
107
+ return
108
+
109
+ if not auto_apply:
110
+ apply = typer.confirm(f"\nā“ Apply {len(changes)} fix(es)?", default=False)
111
+ if not apply:
112
+ typer.echo("āŒ Fixes not applied")
113
+ return
114
+
115
+ # Apply fixes
116
+ typer.echo("\n✨ Applying fixes...")
117
+ result = diff_engine.apply_changes(proposal, backup=True)
118
+
119
+ if result.success:
120
+ typer.echo(f"āœ… Successfully fixed {len(result.files_changed)} file(s)")
121
+ if result.backup_id:
122
+ typer.echo(f"šŸ’¾ Backup created: {result.backup_id}")
123
+ typer.echo(f" Rollback with: cg v2 rollback {result.backup_id}")
124
+
125
+ # Re-check for remaining errors
126
+ typer.echo("\nšŸ” Re-checking for errors...")
127
+ remaining = validator.diagnose_project(project_path)
128
+ if remaining:
129
+ typer.echo(f"āš ļø {len(remaining)} error(s) remain (require manual fixing)")
130
+ else:
131
+ typer.echo("āœ… All errors fixed!")
132
+ else:
133
+ typer.echo(f"āŒ Failed to apply fixes: {result.error}")
@@ -0,0 +1,230 @@
1
+ """CLI commands for refactoring operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import List, Optional
7
+
8
+ import typer
9
+
10
+ from . import config
11
+ from .diff_engine import DiffEngine
12
+ from .refactor_agent import RefactorAgent
13
+ from .storage import GraphStore, ProjectManager
14
+
15
+ # Create sub-app for refactor commands
16
+ refactor_app = typer.Typer(help="Safe refactoring with dependency tracking")
17
+
18
+
19
+ def _get_refactor_agent(pm: ProjectManager) -> RefactorAgent:
20
+ """Get RefactorAgent with current project context."""
21
+ project = pm.get_current_project()
22
+ if not project:
23
+ raise typer.BadParameter("No project loaded. Use 'cg load-project <name>' or run 'cg index <path>'.")
24
+
25
+ project_dir = pm.project_dir(project)
26
+ if not project_dir.exists():
27
+ raise typer.BadParameter(f"Loaded project '{project}' does not exist in memory.")
28
+
29
+ store = GraphStore(project_dir)
30
+ return RefactorAgent(store)
31
+
32
+
33
+ @refactor_app.command("rename")
34
+ def rename_symbol(
35
+ old_name: str = typer.Argument(..., help="Current symbol name"),
36
+ new_name: str = typer.Argument(..., help="New symbol name"),
37
+ preview_only: bool = typer.Option(False, "--preview", "-p", help="Preview changes without applying"),
38
+ auto_apply: bool = typer.Option(False, "--auto-apply", "-y", help="Apply changes without confirmation"),
39
+ ):
40
+ """Rename a symbol and update all references."""
41
+ pm = ProjectManager()
42
+ agent = _get_refactor_agent(pm)
43
+
44
+ typer.echo(f"šŸ”„ Renaming '{old_name}' to '{new_name}'...")
45
+
46
+ try:
47
+ plan = agent.rename_symbol(old_name, new_name)
48
+ except ValueError as e:
49
+ typer.echo(f"āŒ Error: {e}")
50
+ raise typer.Exit(1)
51
+
52
+ # Show refactoring plan
53
+ typer.echo(f"\nšŸ“ Refactoring Plan: {plan.description}")
54
+ typer.echo(f" Files to modify: {len(plan.changes)}")
55
+ typer.echo(f" Call sites to update: {plan.num_call_sites}")
56
+ typer.echo("")
57
+
58
+ # Show changes
59
+ diff_engine = DiffEngine()
60
+ for change in plan.changes:
61
+ typer.echo(f"{'='*60}")
62
+ typer.echo(f"[MODIFY] {change.file_path}")
63
+ typer.echo(f"{'='*60}")
64
+ if change.diff:
65
+ typer.echo(change.diff)
66
+ typer.echo("")
67
+
68
+ if preview_only:
69
+ typer.echo("šŸ“‹ Preview only mode - no changes applied")
70
+ return
71
+
72
+ if not auto_apply:
73
+ apply = typer.confirm("\nā“ Apply refactoring?", default=False)
74
+ if not apply:
75
+ typer.echo("āŒ Refactoring cancelled")
76
+ return
77
+
78
+ # Apply changes
79
+ typer.echo("\n✨ Applying refactoring...")
80
+
81
+ # Create a CodeProposal-like structure for applying
82
+ from .models_v2 import CodeProposal
83
+ proposal = CodeProposal(
84
+ id=str(plan.description),
85
+ description=plan.description,
86
+ changes=plan.changes
87
+ )
88
+
89
+ result = diff_engine.apply_changes(proposal, backup=True)
90
+
91
+ if result.success:
92
+ typer.echo(f"āœ… Successfully refactored {len(result.files_changed)} file(s)")
93
+ if result.backup_id:
94
+ typer.echo(f"šŸ’¾ Backup created: {result.backup_id}")
95
+ typer.echo(f" Rollback with: cg v2 rollback {result.backup_id}")
96
+ else:
97
+ typer.echo(f"āŒ Failed to apply refactoring: {result.error}")
98
+
99
+
100
+ @refactor_app.command("extract-function")
101
+ def extract_function(
102
+ file_path: str = typer.Argument(..., help="File containing code to extract"),
103
+ start_line: int = typer.Argument(..., help="Start line number"),
104
+ end_line: int = typer.Argument(..., help="End line number"),
105
+ function_name: str = typer.Argument(..., help="Name for the new function"),
106
+ preview_only: bool = typer.Option(False, "--preview", "-p", help="Preview changes without applying"),
107
+ auto_apply: bool = typer.Option(False, "--auto-apply", "-y", help="Apply changes without confirmation"),
108
+ ):
109
+ """Extract code range into a new function."""
110
+ pm = ProjectManager()
111
+ agent = _get_refactor_agent(pm)
112
+
113
+ typer.echo(f"šŸ“¤ Extracting lines {start_line}-{end_line} to function '{function_name}'...")
114
+
115
+ try:
116
+ plan = agent.extract_function(file_path, start_line, end_line, function_name)
117
+ except ValueError as e:
118
+ typer.echo(f"āŒ Error: {e}")
119
+ raise typer.Exit(1)
120
+
121
+ # Show plan
122
+ typer.echo(f"\nšŸ“ Refactoring Plan: {plan.description}")
123
+ typer.echo("")
124
+
125
+ # Show changes
126
+ diff_engine = DiffEngine()
127
+ for change in plan.changes:
128
+ typer.echo(f"{'='*60}")
129
+ typer.echo(f"[MODIFY] {change.file_path}")
130
+ typer.echo(f"{'='*60}")
131
+ if change.diff:
132
+ typer.echo(change.diff)
133
+ typer.echo("")
134
+
135
+ if preview_only:
136
+ typer.echo("šŸ“‹ Preview only mode - no changes applied")
137
+ return
138
+
139
+ if not auto_apply:
140
+ apply = typer.confirm("\nā“ Apply refactoring?", default=False)
141
+ if not apply:
142
+ typer.echo("āŒ Refactoring cancelled")
143
+ return
144
+
145
+ # Apply changes
146
+ typer.echo("\n✨ Applying refactoring...")
147
+
148
+ from .models_v2 import CodeProposal
149
+ proposal = CodeProposal(
150
+ id=str(plan.description),
151
+ description=plan.description,
152
+ changes=plan.changes
153
+ )
154
+
155
+ result = diff_engine.apply_changes(proposal, backup=True)
156
+
157
+ if result.success:
158
+ typer.echo(f"āœ… Successfully refactored {len(result.files_changed)} file(s)")
159
+ if result.backup_id:
160
+ typer.echo(f"šŸ’¾ Backup created: {result.backup_id}")
161
+ else:
162
+ typer.echo(f"āŒ Failed to apply refactoring: {result.error}")
163
+
164
+
165
+ @refactor_app.command("extract-service")
166
+ def extract_service(
167
+ symbols: List[str] = typer.Argument(..., help="Function names to extract (space-separated)"),
168
+ target_file: str = typer.Option(..., "--target", "-t", help="Target service file path"),
169
+ preview_only: bool = typer.Option(False, "--preview", "-p", help="Preview changes without applying"),
170
+ auto_apply: bool = typer.Option(False, "--auto-apply", "-y", help="Apply changes without confirmation"),
171
+ ):
172
+ """Extract multiple functions to a new service file."""
173
+ pm = ProjectManager()
174
+ agent = _get_refactor_agent(pm)
175
+
176
+ typer.echo(f"šŸ“¤ Extracting {len(symbols)} function(s) to {target_file}...")
177
+
178
+ try:
179
+ plan = agent.extract_service(symbols, target_file)
180
+ except ValueError as e:
181
+ typer.echo(f"āŒ Error: {e}")
182
+ raise typer.Exit(1)
183
+
184
+ # Show plan
185
+ typer.echo(f"\nšŸ“ Refactoring Plan: {plan.description}")
186
+ typer.echo(f" Files to create: {sum(1 for c in plan.changes if c.change_type == 'create')}")
187
+ typer.echo(f" Files to modify: {sum(1 for c in plan.changes if c.change_type == 'modify')}")
188
+ typer.echo(f" Call sites to update: {plan.num_call_sites}")
189
+ typer.echo("")
190
+
191
+ # Show changes
192
+ diff_engine = DiffEngine()
193
+ for change in plan.changes:
194
+ typer.echo(f"{'='*60}")
195
+ typer.echo(f"[{change.change_type.upper()}] {change.file_path}")
196
+ typer.echo(f"{'='*60}")
197
+ if change.change_type == "create":
198
+ typer.echo(change.new_content[:500] + "..." if len(change.new_content or "") > 500 else change.new_content)
199
+ elif change.diff:
200
+ typer.echo(change.diff)
201
+ typer.echo("")
202
+
203
+ if preview_only:
204
+ typer.echo("šŸ“‹ Preview only mode - no changes applied")
205
+ return
206
+
207
+ if not auto_apply:
208
+ apply = typer.confirm("\nā“ Apply refactoring?", default=False)
209
+ if not apply:
210
+ typer.echo("āŒ Refactoring cancelled")
211
+ return
212
+
213
+ # Apply changes
214
+ typer.echo("\n✨ Applying refactoring...")
215
+
216
+ from .models_v2 import CodeProposal
217
+ proposal = CodeProposal(
218
+ id=str(plan.description),
219
+ description=plan.description,
220
+ changes=plan.changes
221
+ )
222
+
223
+ result = diff_engine.apply_changes(proposal, backup=True)
224
+
225
+ if result.success:
226
+ typer.echo(f"āœ… Successfully refactored {len(result.files_changed)} file(s)")
227
+ if result.backup_id:
228
+ typer.echo(f"šŸ’¾ Backup created: {result.backup_id}")
229
+ else:
230
+ typer.echo(f"āŒ Failed to apply refactoring: {result.error}")