Skip to content
This repository was archived by the owner on Sep 23, 2025. It is now read-only.

Commit 3f6ef26

Browse files
committed
Implement IPC blocking mechanism for user feedback
- Add UserFeedback message type and UserFeedbackPayload struct - Add pending_feedback HashMap to track waiting MCP tools - Implement wait_for_user_feedback with oneshot channel blocking - Handle incoming UserFeedback messages in response reader task - Convert IPC payload to UserFeedback struct for MCP tools Server-side blocking pattern now complete - MCP tools will block until VSCode extension sends user_feedback IPC messages. Addresses #22 - implements the IPC layer for LLM roundtrip
1 parent 34ebcf3 commit 3f6ef26

File tree

2 files changed

+83
-12
lines changed

2 files changed

+83
-12
lines changed

server/src/ipc.rs

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
use crate::types::{
77
FindAllReferencesPayload, GetSelectionResult, GoodbyePayload, IPCMessage, IPCMessageType,
88
LogLevel, LogParams, PoloPayload, PresentReviewParams, PresentReviewResult,
9-
ResolveSymbolByNamePayload, ResponsePayload, SyntheticPRPayload,
9+
ResolveSymbolByNamePayload, ResponsePayload, SyntheticPRPayload, UserFeedbackPayload,
1010
};
1111
use futures::FutureExt;
1212
use 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.

server/src/types.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,8 @@ pub enum IPCMessageType {
194194
CreateSyntheticPr,
195195
/// Update synthetic pull request
196196
UpdateSyntheticPr,
197+
/// User feedback from VSCode extension (comments, review completion)
198+
UserFeedback,
197199
}
198200

199201
/// Payload for synthetic PR creation/update messages
@@ -207,3 +209,16 @@ pub struct SyntheticPRPayload {
207209
pub comment_threads: Vec<crate::synthetic_pr::CommentThread>,
208210
pub status: String,
209211
}
212+
213+
/// Payload for user feedback messages from VSCode extension
214+
#[derive(Debug, Clone, Deserialize, Serialize)]
215+
pub struct UserFeedbackPayload {
216+
pub review_id: String,
217+
pub feedback_type: String, // "comment" or "complete_review"
218+
pub file_path: Option<String>,
219+
pub line_number: Option<u32>,
220+
pub comment_text: Option<String>,
221+
pub completion_action: Option<String>, // "request_changes", "checkpoint", "return"
222+
pub additional_notes: Option<String>,
223+
pub context_lines: Option<Vec<String>>,
224+
}

0 commit comments

Comments
 (0)