@@ -9,7 +9,7 @@ use tokio::signal;
99use tokio:: sync:: mpsc;
1010use tokio_util:: sync:: CancellationToken ;
1111
12- use crate :: cli:: Cli ;
12+ use crate :: cli:: { Cli , Commands } ;
1313use crate :: config:: Config ;
1414use crate :: error:: { Error , Result } ;
1515use crate :: services:: {
@@ -44,7 +44,7 @@ impl App {
4444
4545 // Handle subcommands
4646 if let Some ( ref cmd) = self . cli . command {
47- return self . handle_command ( cmd) ;
47+ return self . handle_command ( cmd) . await ;
4848 }
4949
5050 self . generate_commit ( ) . await
@@ -216,19 +216,23 @@ impl App {
216216 Ok ( ( ) )
217217 }
218218
219- fn handle_command ( & self , cmd : & crate :: cli :: Commands ) -> Result < ( ) > {
219+ async fn handle_command ( & self , cmd : & Commands ) -> Result < ( ) > {
220220 match cmd {
221- crate :: cli :: Commands :: Init => {
221+ Commands :: Init => {
222222 let path = Config :: create_default ( ) ?;
223223 println ! ( "Created config: {}" , path. display( ) ) ;
224224 Ok ( ( ) )
225225 }
226- crate :: cli :: Commands :: Config => {
226+ Commands :: Config => {
227227 println ! ( "Provider: {}" , self . config. provider) ;
228228 println ! ( "Model: {}" , self . config. model) ;
229229 println ! ( "Ollama host: {}" , self . config. ollama_host) ;
230230 println ! ( "Max diff lines: {}" , self . config. max_diff_lines) ;
231231 println ! ( "Max file lines: {}" , self . config. max_file_lines) ;
232+ println ! ( "Max context chars: {}" , self . config. max_context_chars) ;
233+ println ! ( "Timeout: {}s" , self . config. timeout_secs) ;
234+ println ! ( "Temperature: {}" , self . config. temperature) ;
235+ println ! ( "Max tokens: {}" , self . config. num_predict) ;
232236 println ! ( ) ;
233237 println ! ( "[format]" ) ;
234238 println ! ( " include_body: {}" , self . config. format. include_body) ;
@@ -239,7 +243,90 @@ impl App {
239243 ) ;
240244 Ok ( ( ) )
241245 }
246+ Commands :: Doctor => self . run_doctor ( ) . await ,
247+ Commands :: Completions { shell } => {
248+ let mut cmd = <Cli as clap:: CommandFactory >:: command ( ) ;
249+ clap_complete:: generate ( * shell, & mut cmd, "commitbee" , & mut std:: io:: stdout ( ) ) ;
250+ Ok ( ( ) )
251+ }
252+ }
253+ }
254+
255+ async fn run_doctor ( & self ) -> Result < ( ) > {
256+ eprintln ! ( "{} Running diagnostics...\n " , style( "→" ) . cyan( ) ) ;
257+
258+ // Config summary
259+ eprintln ! ( "{}" , style( "Configuration" ) . bold( ) . underlined( ) ) ;
260+ eprintln ! ( " Provider: {}" , self . config. provider) ;
261+ eprintln ! ( " Model: {}" , self . config. model) ;
262+ eprintln ! ( " Timeout: {}s" , self . config. timeout_secs) ;
263+ if let Some ( ref path) = Config :: config_path ( ) {
264+ let status = if path. exists ( ) { "found" } else { "not found" } ;
265+ eprintln ! ( " Config file: {} ({})" , path. display( ) , status) ;
266+ }
267+ eprintln ! ( ) ;
268+
269+ // Provider connectivity
270+ eprintln ! ( "{}" , style( "Provider Check" ) . bold( ) . underlined( ) ) ;
271+ match self . config . provider {
272+ crate :: config:: Provider :: Ollama => {
273+ eprint ! ( " Ollama ({}): " , self . config. ollama_host) ;
274+ let provider = llm:: create_provider ( & self . config ) ?;
275+ match provider. verify ( ) . await {
276+ Ok ( ( ) ) => {
277+ eprintln ! ( "{}" , style( "OK" ) . green( ) . bold( ) ) ;
278+ eprintln ! (
279+ " Model '{}': {}" ,
280+ self . config. model,
281+ style( "available" ) . green( )
282+ ) ;
283+ }
284+ Err ( Error :: OllamaNotRunning { .. } ) => {
285+ eprintln ! ( "{}" , style( "NOT RUNNING" ) . red( ) . bold( ) ) ;
286+ eprintln ! ( " Start with: {}" , style( "ollama serve" ) . yellow( ) ) ;
287+ }
288+ Err ( Error :: ModelNotFound { ref available, .. } ) => {
289+ eprintln ! ( "{}" , style( "connected" ) . green( ) ) ;
290+ eprintln ! (
291+ " Model '{}': {}" ,
292+ self . config. model,
293+ style( "NOT FOUND" ) . red( ) . bold( )
294+ ) ;
295+ eprintln ! (
296+ " Pull with: {}" ,
297+ style( format!( "ollama pull {}" , self . config. model) ) . yellow( )
298+ ) ;
299+ if !available. is_empty ( ) {
300+ eprintln ! ( " Available: {}" , available. join( ", " ) ) ;
301+ }
302+ }
303+ Err ( e) => {
304+ eprintln ! ( "{}: {}" , style( "ERROR" ) . red( ) . bold( ) , e) ;
305+ }
306+ }
307+ }
308+ other => {
309+ eprint ! ( " {} API key: " , other) ;
310+ if self . config . api_key . is_some ( ) {
311+ eprintln ! ( "{}" , style( "configured" ) . green( ) ) ;
312+ } else {
313+ eprintln ! ( "{}" , style( "MISSING" ) . red( ) . bold( ) ) ;
314+ }
315+ }
242316 }
317+ eprintln ! ( ) ;
318+
319+ // Git check
320+ eprintln ! ( "{}" , style( "Git Repository" ) . bold( ) . underlined( ) ) ;
321+ match GitService :: discover ( ) {
322+ Ok ( _) => eprintln ! ( " Repository: {}" , style( "found" ) . green( ) ) ,
323+ Err ( _) => eprintln ! ( " Repository: {}" , style( "NOT FOUND" ) . red( ) . bold( ) ) ,
324+ }
325+
326+ eprintln ! ( ) ;
327+ eprintln ! ( "{} Diagnostics complete." , style( "✓" ) . green( ) . bold( ) ) ;
328+
329+ Ok ( ( ) )
243330 }
244331
245332 fn print_status ( & self , msg : & str ) {
0 commit comments