1
+ import json
2
+ import os
3
+ import shutil
4
+ import subprocess
5
+ import sys
6
+ from pathlib import Path
7
+ from typing import List , Tuple
8
+
9
+ from codeflash .cli_cmds .console import logger , paneled_text
10
+ from codeflash .version import __version__ as version
11
+
12
+
13
+ def run_doctor () -> None :
14
+ """Run comprehensive setup verification for Codeflash."""
15
+ paneled_text (
16
+ "🩺 Codeflash Doctor - Diagnosing your setup..." ,
17
+ panel_args = {"title" : "Setup Verification" , "expand" : False },
18
+ text_args = {"style" : "bold blue" }
19
+ )
20
+
21
+ checks = [
22
+ ("Python Environment" , check_python_environment ),
23
+ ("Codeflash Installation" , check_codeflash_installation ),
24
+ ("VS Code Python Extension" , check_vscode_python_extension ),
25
+ ("LSP Server Connection" , check_lsp_server_connection ),
26
+ ("Git Repository" , check_git_repository ),
27
+ ("Project Configuration" , check_project_configuration ),
28
+ ]
29
+
30
+ results = []
31
+ all_passed = True
32
+
33
+ for check_name , check_func in checks :
34
+ logger .info (f"Checking { check_name } ..." )
35
+ success , message = check_func ()
36
+ results .append ((check_name , success , message ))
37
+ if not success :
38
+ all_passed = False
39
+
40
+ print_results (results , all_passed )
41
+
42
+
43
+ def check_python_environment () -> Tuple [bool , str ]:
44
+ """Check Python version and environment."""
45
+ try :
46
+ python_version = f"{ sys .version_info .major } .{ sys .version_info .minor } .{ sys .version_info .micro } "
47
+ if sys .version_info < (3 , 8 ):
48
+ return False , f"Python { python_version } found. Python 3.8+ required."
49
+ return True , f"Python { python_version } ✓"
50
+ except Exception as e :
51
+ return False , f"Failed to check Python version: { e } "
52
+
53
+
54
+ def check_codeflash_installation () -> Tuple [bool , str ]:
55
+ """Verify Codeflash is properly installed."""
56
+ try :
57
+ return True , f"Codeflash { version } installed ✓"
58
+ except Exception as e :
59
+ return False , f"Codeflash installation check failed: { e } "
60
+
61
+
62
+ def check_vscode_python_extension () -> Tuple [bool , str ]:
63
+ """Check if VS Code Python extension is installed."""
64
+ try :
65
+ code_cmd = shutil .which ("code" )
66
+ if not code_cmd :
67
+ return False , "VS Code 'code' command not found in PATH"
68
+
69
+ result = subprocess .run (
70
+ [code_cmd , "--list-extensions" ],
71
+ capture_output = True ,
72
+ text = True ,
73
+ timeout = 10
74
+ )
75
+
76
+ if result .returncode != 0 :
77
+ return False , f"Failed to list VS Code extensions: { result .stderr } "
78
+
79
+ extensions = result .stdout .strip ().split ('\n ' )
80
+ python_extensions = [ext for ext in extensions if 'python' in ext .lower ()]
81
+
82
+ if not python_extensions :
83
+ return False , "Python extension not found. Install the Python extension for VS Code."
84
+
85
+ return True , f"VS Code Python extension found: { ', ' .join (python_extensions )} ✓"
86
+
87
+ except subprocess .TimeoutExpired :
88
+ return False , "VS Code extension check timed out"
89
+ except Exception as e :
90
+ return False , f"VS Code extension check failed: { e } "
91
+
92
+
93
+ def check_lsp_server_connection () -> Tuple [bool , str ]:
94
+ """Test LSP server connectivity."""
95
+ try :
96
+ from codeflash .lsp .server import CodeflashLanguageServer
97
+
98
+ # Test that we can instantiate the server (basic smoke test)
99
+ server_class = CodeflashLanguageServer
100
+ if hasattr (server_class , 'initialize_optimizer' ):
101
+ return True , "LSP server available ✓"
102
+ else :
103
+ return True , "LSP server module loaded successfully ✓"
104
+
105
+ except ImportError as e :
106
+ return False , f"LSP server import failed: { e } "
107
+ except Exception as e :
108
+ return False , f"LSP server check failed: { e } "
109
+
110
+
111
+ def check_git_repository () -> Tuple [bool , str ]:
112
+ """Check if running in a git repository."""
113
+ try :
114
+ result = subprocess .run (
115
+ ["git" , "rev-parse" , "--git-dir" ],
116
+ capture_output = True ,
117
+ text = True ,
118
+ timeout = 5
119
+ )
120
+
121
+ if result .returncode == 0 :
122
+ return True , "Git repository detected ✓"
123
+ else :
124
+ return False , "No git repository found. Initialize with 'git init'"
125
+
126
+ except subprocess .TimeoutExpired :
127
+ return False , "Git check timed out"
128
+ except FileNotFoundError :
129
+ return False , "Git not found in PATH"
130
+ except Exception as e :
131
+ return False , f"Git check failed: { e } "
132
+
133
+
134
+ def check_project_configuration () -> Tuple [bool , str ]:
135
+ """Check for project configuration files."""
136
+ try :
137
+ config_files = ["pyproject.toml" , "setup.py" , "requirements.txt" , "setup.cfg" ]
138
+ found_configs = []
139
+
140
+ for config_file in config_files :
141
+ if Path (config_file ).exists ():
142
+ found_configs .append (config_file )
143
+
144
+ if found_configs :
145
+ return True , f"Project configuration found: { ', ' .join (found_configs )} ✓"
146
+ else :
147
+ return False , "No project configuration files found (pyproject.toml, setup.py, etc.)"
148
+
149
+ except Exception as e :
150
+ return False , f"Project configuration check failed: { e } "
151
+
152
+
153
+ def print_results (results : List [Tuple [str , bool , str ]], all_passed : bool ) -> None :
154
+ """Print the diagnostic results in a formatted way."""
155
+ print ("\n " + "=" * 60 )
156
+ print ("🩺 CODEFLASH SETUP DIAGNOSIS RESULTS" )
157
+ print ("=" * 60 )
158
+
159
+ for check_name , success , message in results :
160
+ status = "✅ PASS" if success else "❌ FAIL"
161
+ print (f"{ status :8} | { check_name :25} | { message } " )
162
+
163
+ print ("=" * 60 )
164
+
165
+ if all_passed :
166
+ paneled_text (
167
+ "🎉 Your Codeflash setup is perfect! 🎉\n \n "
168
+ "All checks passed successfully. You're ready to optimize your code!\n \n "
169
+ "Next steps:\n "
170
+ "• Run 'codeflash init' to initialize a project\n "
171
+ "• Use 'codeflash --file <filename>' to optimize a specific file\n "
172
+ "• Try 'codeflash --verify-setup' for an end-to-end test" ,
173
+ panel_args = {"title" : "✅ SUCCESS" , "expand" : False },
174
+ text_args = {"style" : "bold green" }
175
+ )
176
+ else :
177
+ failed_checks = [name for name , success , _ in results if not success ]
178
+ paneled_text (
179
+ f"⚠️ Setup Issues Detected\n \n "
180
+ f"The following checks failed:\n "
181
+ f"• { chr (10 ).join (failed_checks )} \n \n "
182
+ f"Please address these issues and run 'codeflash doctor' again.\n \n "
183
+ f"For help, visit: https://codeflash.ai/docs" ,
184
+ panel_args = {"title" : "❌ ISSUES FOUND" , "expand" : False },
185
+ text_args = {"style" : "bold yellow" }
186
+ )
187
+ sys .exit (1 )
0 commit comments