@@ -17,7 +17,7 @@ use tracing::info;
1717
1818use crate :: dialect:: DialectInterpreter ;
1919use crate :: ipc:: IPCCommunicator ;
20- use crate :: synthetic_pr:: { RequestReviewParams , UpdateReviewParams } ;
20+ use crate :: synthetic_pr:: { RequestReviewParams , UpdateReviewParams , UserFeedback } ;
2121use crate :: types:: { LogLevel , PresentReviewParams } ;
2222use serde:: { Deserialize , Serialize } ;
2323
@@ -84,6 +84,73 @@ impl DialecticServer {
8484 & self . ipc
8585 }
8686
87+ /// Format user feedback into clear instructions for the LLM
88+ fn format_user_feedback_message ( & self , feedback : & UserFeedback ) -> String {
89+ match feedback. feedback_type {
90+ crate :: synthetic_pr:: FeedbackType :: Comment => {
91+ let file_path = feedback. file_path . as_deref ( ) . unwrap_or ( "unknown file" ) ;
92+ let line_number = feedback. line_number . unwrap_or ( 0 ) ;
93+ let comment_text = feedback. comment_text . as_deref ( ) . unwrap_or ( "(no comment)" ) ;
94+
95+ let context = if let Some ( lines) = & feedback. context_lines {
96+ format ! ( "\n \n Code context:\n ```\n {}\n ```" , lines. join( "\n " ) )
97+ } else {
98+ String :: new ( )
99+ } ;
100+
101+ format ! (
102+ "The user reviewed your code changes and left a comment on file `{}` at line {}:\n \n \
103+ User comment: '{}'{}\n \n \
104+ Please analyze the user's feedback and prepare a thoughtful response addressing their concern. \
105+ Do NOT modify any files on disk.\n \n \
106+ When ready, invoke the update_review tool with:\n \
107+ - review_id: '{}'\n \
108+ - action: AddComment\n \
109+ - comment: {{ response: 'Your response text here' }}\n \n \
110+ After responding, invoke update_review again with action: WaitForFeedback to continue the conversation.",
111+ file_path,
112+ line_number,
113+ comment_text,
114+ context,
115+ feedback. review_id. as_deref( ) . unwrap_or( "unknown" )
116+ )
117+ }
118+ crate :: synthetic_pr:: FeedbackType :: CompleteReview => {
119+ let action = feedback. completion_action . as_ref ( ) ;
120+ let notes = feedback. additional_notes . as_deref ( ) . unwrap_or ( "" ) ;
121+
122+ let notes_section = if !notes. is_empty ( ) {
123+ format ! ( "\n Additional notes: '{}'\n " , notes)
124+ } else {
125+ String :: new ( )
126+ } ;
127+
128+ match action {
129+ Some ( crate :: synthetic_pr:: CompletionAction :: RequestChanges ) => format ! (
130+ "User completed their review and selected: 'Request agent to make changes'{}\n \
131+ Based on the review discussion, please implement the requested changes. \
132+ You may now edit files as needed.\n \n \
133+ When finished, invoke: update_review(review_id: '{}', action: Approve)",
134+ notes_section,
135+ feedback. review_id. as_deref( ) . unwrap_or( "unknown" )
136+ ) ,
137+ Some ( crate :: synthetic_pr:: CompletionAction :: Checkpoint ) => format ! (
138+ "User completed their review and selected: 'Request agent to checkpoint this work'{}\n \
139+ Please commit the current changes and document the work completed.\n \n \
140+ When finished, invoke: update_review(review_id: '{}', action: Approve)",
141+ notes_section,
142+ feedback. review_id. as_deref( ) . unwrap_or( "unknown" )
143+ ) ,
144+ _ => format ! (
145+ "User completed their review and selected: 'Return to agent without explicit request'{}\n \
146+ The review is complete. You may proceed as you see fit.",
147+ notes_section
148+ ) ,
149+ }
150+ }
151+ }
152+ }
153+
87154 /// Ensure the message bus daemon is running for the given VSCode PID
88155 async fn ensure_daemon_running ( vscode_pid : u32 ) -> Result < ( ) > {
89156 crate :: daemon:: spawn_daemon_process ( vscode_pid) . await
@@ -359,7 +426,7 @@ impl DialecticServer {
359426 . await ;
360427
361428 // Execute the synthetic PR creation
362- let result = crate :: synthetic_pr:: request_review ( params)
429+ let result = crate :: synthetic_pr:: harvest_review_data ( params)
363430 . await
364431 . map_err ( |e| {
365432 McpError :: internal_error (
@@ -391,19 +458,17 @@ impl DialecticServer {
391458 . await ;
392459
393460 // Send initial review to VSCode extension and wait for user response
394- let user_response = self . ipc
395- . send_review_update ( & result)
396- . await
397- . map_err ( |e| {
398- McpError :: internal_error (
399- "Failed to send initial review" ,
400- Some ( serde_json:: json!( {
401- "error" : e. to_string( )
402- } ) ) ,
403- )
404- } ) ?;
461+ let user_feedback = self . ipc . send_review_update ( & result) . await . map_err ( |e| {
462+ McpError :: internal_error (
463+ "Failed to send initial review" ,
464+ Some ( serde_json:: json!( {
465+ "error" : e. to_string( )
466+ } ) ) ,
467+ )
468+ } ) ?;
405469
406- Ok ( CallToolResult :: success ( vec ! [ Content :: text( user_response) ] ) )
470+ let message = self . format_user_feedback_message ( & user_feedback) ;
471+ Ok ( CallToolResult :: success ( vec ! [ Content :: text( message) ] ) )
407472 }
408473
409474 // ANCHOR: update_review_tool
@@ -440,7 +505,8 @@ impl DialecticServer {
440505 } ) ?;
441506
442507 // 2. Send updated state to VSCode extension via IPC and wait for response
443- let user_response = self . ipc
508+ let user_feedback = self
509+ . ipc
444510 . send_review_update ( & updated_review)
445511 . await
446512 . map_err ( |e| {
@@ -452,8 +518,9 @@ impl DialecticServer {
452518 )
453519 } ) ?;
454520
455- // 3. Return user's response to LLM
456- Ok ( CallToolResult :: success ( vec ! [ Content :: text( user_response) ] ) )
521+ // 3. Return formatted user response to LLM
522+ let message = self . format_user_feedback_message ( & user_feedback) ;
523+ Ok ( CallToolResult :: success ( vec ! [ Content :: text( message) ] ) )
457524 }
458525
459526 /// Get the status of the current synthetic pull request
0 commit comments