acp_utils/server/
actor.rs1use agent_client_protocol::{self as acp, Client};
2use tokio::sync::{mpsc, oneshot};
3use tracing::debug;
4
5use super::AcpServerError;
6
7#[derive(Debug)]
9pub enum AcpRequest {
10 SessionNotification {
11 notification: Box<acp::SessionNotification>,
12 response_tx: oneshot::Sender<Result<(), AcpServerError>>,
13 },
14 ExtNotification {
15 notification: acp::ExtNotification,
16 response_tx: oneshot::Sender<Result<(), AcpServerError>>,
17 },
18 RequestPermission {
19 request: Box<acp::RequestPermissionRequest>,
20 response_tx: oneshot::Sender<Result<acp::RequestPermissionResponse, AcpServerError>>,
21 },
22 ExtMethod {
23 request: acp::ExtRequest,
24 response_tx: oneshot::Sender<Result<acp::ExtResponse, AcpServerError>>,
25 },
26}
27
28pub struct AcpActor {
31 conn: acp::AgentSideConnection,
32 request_rx: mpsc::UnboundedReceiver<AcpRequest>,
33}
34
35impl AcpActor {
36 pub fn new(conn: acp::AgentSideConnection, request_rx: mpsc::UnboundedReceiver<AcpRequest>) -> Self {
37 Self { conn, request_rx }
38 }
39
40 pub async fn run(mut self) {
42 debug!("ACP actor starting");
43
44 while let Some(request) = self.request_rx.recv().await {
45 self.handle_request(request).await;
46 }
47
48 debug!("ACP actor stopping");
49 }
50
51 async fn handle_request(&self, request: AcpRequest) {
52 match request {
53 AcpRequest::SessionNotification { notification, response_tx } => {
54 debug!("ACP actor: session_notification");
55 let result = self
56 .conn
57 .session_notification(*notification)
58 .await
59 .map_err(|e| AcpServerError::Protocol(format!("session_notification: {e}")));
60 let _ = response_tx.send(result);
61 }
62
63 AcpRequest::ExtNotification { notification, response_tx } => {
64 debug!("ACP actor: ext_notification {}", notification.method);
65 let result = self
66 .conn
67 .ext_notification(notification)
68 .await
69 .map_err(|e| AcpServerError::Protocol(format!("ext_notification: {e}")));
70 let _ = response_tx.send(result);
71 }
72
73 AcpRequest::RequestPermission { request, response_tx } => {
74 debug!("ACP actor: request_permission");
75 let result = self
76 .conn
77 .request_permission(*request)
78 .await
79 .map_err(|e| AcpServerError::Protocol(format!("request_permission: {e}")));
80 let _ = response_tx.send(result);
81 }
82
83 AcpRequest::ExtMethod { request, response_tx } => {
84 debug!("ACP actor: ext_method {}", request.method);
85 let result = self
86 .conn
87 .ext_method(request)
88 .await
89 .map_err(|e| AcpServerError::Protocol(format!("ext_method: {e}")));
90 let _ = response_tx.send(result);
91 }
92 }
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[tokio::test]
101 async fn test_actor_exits_on_channel_drop() {
102 let (tx, rx) = mpsc::unbounded_channel::<AcpRequest>();
103 drop(tx);
105
106 assert!(rx.is_empty());
110 }
111}