66use crate :: types:: {
77 FindAllReferencesPayload , GetSelectionResult , GoodbyePayload , IPCMessage , IPCMessageType ,
88 LogLevel , LogParams , PoloPayload , PresentReviewParams , PresentReviewResult ,
9- ResolveSymbolByNamePayload , ResponsePayload , SyntheticPRPayload ,
9+ ResolveSymbolByNamePayload , ResponsePayload , SyntheticPRPayload , UserFeedbackPayload ,
1010} ;
1111use futures:: FutureExt ;
1212use serde_json;
@@ -76,6 +76,10 @@ struct IPCCommunicatorInner {
7676 /// Enables concurrent request/response handling with proper correlation
7777 pending_requests : HashMap < String , oneshot:: Sender < ResponsePayload > > ,
7878
79+ /// Tracks pending user feedback requests for blocking MCP tools
80+ /// Key: review_id, Value: channel to send UserFeedback back to caller
81+ pending_feedback : HashMap < String , oneshot:: Sender < crate :: synthetic_pr:: UserFeedback > > ,
82+
7983 /// Flag to track if we have an active connection and reader task
8084 /// When true, ensure_connection() is a no-op
8185 connected : bool ,
@@ -97,6 +101,7 @@ impl IPCCommunicator {
97101 inner : Arc :: new ( Mutex :: new ( IPCCommunicatorInner {
98102 write_half : None ,
99103 pending_requests : HashMap :: new ( ) ,
104+ pending_feedback : HashMap :: new ( ) ,
100105 connected : false ,
101106 vscode_pid,
102107 terminal_shell_pid : shell_pid,
@@ -112,6 +117,7 @@ impl IPCCommunicator {
112117 inner : Arc :: new ( Mutex :: new ( IPCCommunicatorInner {
113118 write_half : None ,
114119 pending_requests : HashMap :: new ( ) ,
120+ pending_feedback : HashMap :: new ( ) ,
115121 connected : false ,
116122 vscode_pid : 0 , // Dummy PID for test mode
117123 terminal_shell_pid : 0 , // Dummy PID for test mode
@@ -405,17 +411,33 @@ impl IPCCommunicator {
405411 } ) ;
406412 }
407413
408- // TODO: Implement actual blocking mechanism
409- // This should:
410- // 1. Register a pending feedback request for this review_id
411- // 2. Block until IPC message arrives with user feedback
412- // 3. Return the structured UserFeedback data
413-
414- // For now, return an error indicating this is not yet implemented
415- Err ( IPCError :: ConnectionFailed {
416- path : "user_feedback" . to_string ( ) ,
417- source : std:: io:: Error :: new ( std:: io:: ErrorKind :: NotFound , "wait_for_user_feedback not yet implemented" )
418- } )
414+ // Create a channel to receive the user feedback
415+ let ( sender, receiver) = oneshot:: channel ( ) ;
416+
417+ // Register the pending feedback request
418+ {
419+ let mut inner = self . inner . lock ( ) . await ;
420+ inner. pending_feedback . insert ( review_id. to_string ( ) , sender) ;
421+ }
422+
423+ info ! ( "Waiting for user feedback on review: {}" , review_id) ;
424+
425+ // Block until user feedback arrives via IPC message
426+ match receiver. await {
427+ Ok ( feedback) => {
428+ info ! ( "Received user feedback for review: {}" , review_id) ;
429+ Ok ( feedback)
430+ }
431+ Err ( _) => {
432+ // Channel was dropped, remove from pending requests
433+ let mut inner = self . inner . lock ( ) . await ;
434+ inner. pending_feedback . remove ( review_id) ;
435+ Err ( IPCError :: ConnectionFailed {
436+ path : "user_feedback" . to_string ( ) ,
437+ source : std:: io:: Error :: new ( std:: io:: ErrorKind :: BrokenPipe , "User feedback channel closed" )
438+ } )
439+ }
440+ }
419441 }
420442
421443 /// Gracefully shutdown the IPC communicator, sending Goodbye discovery message
@@ -779,6 +801,40 @@ impl IPCCommunicator {
779801 error ! ( "Failed to send Polo response to Marco: {}" , e) ;
780802 }
781803 }
804+ IPCMessageType :: UserFeedback => {
805+ info ! ( "Received user feedback message" ) ;
806+
807+ // Parse the user feedback payload
808+ let feedback_payload: UserFeedbackPayload = match serde_json:: from_value ( message. payload ) {
809+ Ok ( payload) => payload,
810+ Err ( e) => {
811+ error ! ( "Failed to parse user feedback payload: {}" , e) ;
812+ return ;
813+ }
814+ } ;
815+
816+ // Convert to UserFeedback struct
817+ let user_feedback = crate :: synthetic_pr:: UserFeedback {
818+ review_id : Some ( feedback_payload. review_id . clone ( ) ) ,
819+ feedback_type : feedback_payload. feedback_type ,
820+ file_path : feedback_payload. file_path ,
821+ line_number : feedback_payload. line_number ,
822+ comment_text : feedback_payload. comment_text ,
823+ completion_action : feedback_payload. completion_action ,
824+ additional_notes : feedback_payload. additional_notes ,
825+ context_lines : feedback_payload. context_lines ,
826+ } ;
827+
828+ // Send to waiting MCP tool
829+ let mut inner_guard = inner. lock ( ) . await ;
830+ if let Some ( sender) = inner_guard. pending_feedback . remove ( & feedback_payload. review_id ) {
831+ if let Err ( _) = sender. send ( user_feedback) {
832+ warn ! ( "Failed to send user feedback to waiting MCP tool - receiver dropped" ) ;
833+ }
834+ } else {
835+ warn ! ( "Received user feedback for unknown review ID: {}" , feedback_payload. review_id) ;
836+ }
837+ }
782838 _ => {
783839 // Every message (including the ones we send...) gets rebroadcast to everyone,
784840 // so we can just ignore anything else.
0 commit comments