@@ -2,7 +2,7 @@ use std::io::Write;
22
33use eyre:: Result ;
44use serde:: Deserialize ;
5- use code_agent_sdk:: SymbolInfo ;
5+ use code_agent_sdk:: { SymbolInfo , ApiDiagnosticInfo } ;
66use super :: { InvokeOutput , OutputKind } ;
77use crate :: cli:: agent:: { Agent , PermissionEvalResult } ;
88use crate :: cli:: experiment:: experiment_manager:: { ExperimentManager , ExperimentName } ;
@@ -19,6 +19,7 @@ pub enum Code {
1919 Format ( FormatCodeParams ) ,
2020 GetDocumentSymbols ( GetDocumentSymbolsParams ) ,
2121 LookupSymbols ( LookupSymbolsParams ) ,
22+ GetDiagnostics ( GetDiagnosticsParams ) ,
2223 InitializeWorkspace ,
2324}
2425
@@ -83,6 +84,15 @@ pub struct LookupSymbolsParams {
8384 pub file_path : Option < String > ,
8485}
8586
87+ #[ derive( Debug , Clone , Deserialize ) ]
88+ pub struct GetDiagnosticsParams {
89+ pub file_path : String ,
90+ #[ serde( default ) ]
91+ pub identifier : Option < String > ,
92+ #[ serde( default ) ]
93+ pub previous_result_id : Option < String > ,
94+ }
95+
8696fn default_tab_size ( ) -> i32 { 4 }
8797fn default_insert_spaces ( ) -> bool { true }
8898
@@ -154,6 +164,10 @@ impl Code {
154164 }
155165 Ok ( ( ) )
156166 }
167+ Code :: GetDiagnostics ( params) => {
168+ Self :: validate_file_exists ( os, & params. file_path ) ?;
169+ Ok ( ( ) )
170+ }
157171 Code :: InitializeWorkspace => Ok ( ( ) ) ,
158172 }
159173 }
@@ -205,39 +219,12 @@ impl Code {
205219 if symbols. is_empty ( ) {
206220 queue ! (
207221 _stdout,
208- style:: Print ( "\n 🔍 No symbols found matching \" " ) ,
209- StyledText :: warning_fg( ) ,
210- style:: Print ( & params. symbol_name) ,
211- StyledText :: reset( ) ,
212- style:: Print ( "\" \n " ) ,
222+ style:: Print ( "\n ⚠️ No symbols found\n " ) ,
213223 ) ?;
214224 result = "No symbols found" . to_string ( ) ;
215225 } else {
216- let limit = params. limit . unwrap_or ( 10 ) as usize ;
217- let is_truncated = symbols. len ( ) >= limit;
218-
219- queue ! (
220- _stdout,
221- style:: Print ( "\n 🔍 Found " ) ,
222- StyledText :: success_fg( ) ,
223- style:: Print ( & symbols. len( ) . to_string( ) ) ,
224- StyledText :: reset( ) ,
225- style:: Print ( " symbol(s)" ) ,
226- ) ?;
227-
228- if is_truncated {
229- queue ! (
230- _stdout,
231- style:: Print ( " " ) ,
232- StyledText :: warning_fg( ) ,
233- style:: Print ( "(limited by max results)" ) ,
234- StyledText :: reset( ) ,
235- ) ?;
236- }
237-
238- queue ! ( _stdout, style:: Print ( ":\n " ) ) ?;
226+ queue ! ( _stdout, style:: Print ( "\n " ) ) ?;
239227 Self :: render_symbols ( & symbols, _stdout) ?;
240-
241228 result = format ! ( "{:?}" , symbols) ;
242229 }
243230 }
@@ -265,25 +252,12 @@ impl Code {
265252 if references. is_empty ( ) {
266253 queue ! (
267254 _stdout,
268- style:: Print ( "\n 🔗 No references found for symbol at " ) ,
269- StyledText :: warning_fg( ) ,
270- style:: Print ( & format!( "{}:{}:{}" , params. file_path, params. row, params. column) ) ,
271- StyledText :: reset( ) ,
272- style:: Print ( "\n " ) ,
255+ style:: Print ( "\n ⚠️ No references found\n " ) ,
273256 ) ?;
274257 result = "No references found" . to_string ( ) ;
275258 } else {
276- queue ! (
277- _stdout,
278- style:: Print ( "\n 🔗 Found " ) ,
279- StyledText :: success_fg( ) ,
280- style:: Print ( & references. len( ) . to_string( ) ) ,
281- StyledText :: reset( ) ,
282- style:: Print ( " reference(s) across workspace:\n " ) ,
283- ) ?;
284-
259+ queue ! ( _stdout, style:: Print ( "\n " ) ) ?;
285260 Self :: render_references ( & references, _stdout) ?;
286-
287261 result = format ! ( "{:?}" , references) ;
288262 }
289263 }
@@ -507,6 +481,39 @@ impl Code {
507481 }
508482 }
509483 }
484+ Code :: GetDiagnostics ( params) => {
485+ let request = code_agent_sdk:: model:: types:: GetDocumentDiagnosticsRequest {
486+ file_path : std:: path:: PathBuf :: from ( & params. file_path ) ,
487+ identifier : params. identifier . clone ( ) ,
488+ previous_result_id : params. previous_result_id . clone ( ) ,
489+ } ;
490+
491+ match client. get_document_diagnostics ( request) . await {
492+ Ok ( diagnostics) => {
493+ if diagnostics. is_empty ( ) {
494+ queue ! (
495+ _stdout,
496+ style:: Print ( "\n ✅ No diagnostics found\n " ) ,
497+ ) ?;
498+ result = "No diagnostics found" . to_string ( ) ;
499+ } else {
500+ queue ! ( _stdout, style:: Print ( "\n " ) ) ?;
501+ Self :: render_diagnostics ( & diagnostics, _stdout) ?;
502+ result = format ! ( "{:?}" , diagnostics) ;
503+ }
504+ }
505+ Err ( e) => {
506+ queue ! (
507+ _stdout,
508+ StyledText :: error_fg( ) ,
509+ style:: Print ( "❌ Failed to get diagnostics: " ) ,
510+ StyledText :: reset( ) ,
511+ style:: Print ( & format!( "{}\n " , e) ) ,
512+ ) ?;
513+ result = format ! ( "❌ Failed to get diagnostics: {}" , e) ;
514+ }
515+ }
516+ }
510517 Code :: InitializeWorkspace => {
511518 match client. initialize ( ) . await {
512519 Ok ( init_response) => {
@@ -592,6 +599,103 @@ impl Code {
592599 Ok ( ( ) )
593600 }
594601
602+ fn render_diagnostics ( diagnostics : & [ ApiDiagnosticInfo ] , stdout : & mut impl Write ) -> Result < ( ) > {
603+ use crossterm:: { queue, style} ;
604+ use crate :: theme:: StyledText ;
605+ use code_agent_sdk:: ApiDiagnosticSeverity ;
606+
607+ for ( i, diagnostic) in diagnostics. iter ( ) . enumerate ( ) {
608+ // Determine severity icon and color
609+ let ( severity_icon, severity_text) = match diagnostic. severity {
610+ ApiDiagnosticSeverity :: Error => ( "❌" , "Error" ) ,
611+ ApiDiagnosticSeverity :: Warning => ( "⚠️" , "Warning" ) ,
612+ ApiDiagnosticSeverity :: Information => ( "ℹ️" , "Info" ) ,
613+ ApiDiagnosticSeverity :: Hint => ( "💡" , "Hint" ) ,
614+ } ;
615+
616+ queue ! (
617+ stdout,
618+ style:: Print ( & format!( " {}. {} " , i + 1 , severity_icon) ) ,
619+ ) ?;
620+
621+ // Color based on severity
622+ match diagnostic. severity {
623+ ApiDiagnosticSeverity :: Error => {
624+ queue ! ( stdout, StyledText :: error_fg( ) ) ?;
625+ }
626+ ApiDiagnosticSeverity :: Warning => {
627+ queue ! ( stdout, StyledText :: warning_fg( ) ) ?;
628+ }
629+ _ => {
630+ queue ! ( stdout, StyledText :: info_fg( ) ) ?;
631+ }
632+ }
633+
634+ queue ! (
635+ stdout,
636+ style:: Print ( severity_text) ,
637+ StyledText :: reset( ) ,
638+ style:: Print ( & format!( " at line {}:{}" ,
639+ diagnostic. start_row,
640+ diagnostic. start_column) ) ,
641+ ) ?;
642+
643+ // Show diagnostic source if available
644+ if let Some ( source) = & diagnostic. source {
645+ queue ! (
646+ stdout,
647+ style:: Print ( " [" ) ,
648+ StyledText :: info_fg( ) ,
649+ style:: Print ( source) ,
650+ StyledText :: reset( ) ,
651+ style:: Print ( "]" ) ,
652+ ) ?;
653+ }
654+
655+ // Show diagnostic code if available
656+ if let Some ( code) = & diagnostic. code {
657+ queue ! (
658+ stdout,
659+ style:: Print ( " (" ) ,
660+ style:: Print ( code) ,
661+ style:: Print ( ")" ) ,
662+ ) ?;
663+ }
664+
665+ queue ! ( stdout, style:: Print ( "\n " ) ) ?;
666+
667+ // Show the diagnostic message (indented)
668+ queue ! (
669+ stdout,
670+ style:: Print ( " " ) ,
671+ style:: Print ( & diagnostic. message) ,
672+ style:: Print ( "\n " ) ,
673+ ) ?;
674+
675+ // Show related information if available
676+ if !diagnostic. related_information . is_empty ( ) {
677+ queue ! (
678+ stdout,
679+ style:: Print ( " Related:\n " ) ,
680+ ) ?;
681+ for info in & diagnostic. related_information {
682+ queue ! (
683+ stdout,
684+ style:: Print ( " • " ) ,
685+ StyledText :: info_fg( ) ,
686+ style:: Print ( & info. file_path) ,
687+ StyledText :: reset( ) ,
688+ style:: Print ( & format!( ":{}:{} - {}\n " ,
689+ info. start_row,
690+ info. start_column,
691+ info. message) ) ,
692+ ) ?;
693+ }
694+ }
695+ }
696+ Ok ( ( ) )
697+ }
698+
595699 pub fn queue_description ( & self , output : & mut impl Write ) -> Result < ( ) > {
596700 use crossterm:: { queue, style} ;
597701 use crate :: theme:: StyledText ;
@@ -734,6 +838,15 @@ impl Code {
734838 ) ?;
735839 }
736840 }
841+ Code :: GetDiagnostics ( params) => {
842+ queue ! (
843+ output,
844+ style:: Print ( "🔍 Getting diagnostics for: " ) ,
845+ StyledText :: success_fg( ) ,
846+ style:: Print ( & params. file_path) ,
847+ StyledText :: reset( ) ,
848+ ) ?;
849+ }
737850 Code :: InitializeWorkspace => {
738851 queue ! (
739852 output,
0 commit comments