use super::session_manager::SessionManager;
use acp_utils::notifications::McpRequest;
use agent_client_protocol::schema::{
AuthenticateRequest, CancelNotification, InitializeRequest, ListSessionsRequest, LoadSessionRequest,
NewSessionRequest, PromptRequest, SetSessionConfigOptionRequest,
};
use agent_client_protocol::{
self as acp, Agent, Builder, Client, ConnectionTo, HandleDispatchFrom, JsonRpcResponse, NullRun, Responder,
};
use std::future::Future;
use std::sync::Arc;
pub(crate) fn acp_agent_builder(
manager: Arc<SessionManager>,
) -> Builder<Agent, impl HandleDispatchFrom<Client>, NullRun> {
Agent
.builder()
.on_receive_request(
{
let mgr = manager.clone();
async move |req: InitializeRequest, responder, cx| {
let mgr = mgr.clone();
spawn_task(&cx, responder, async move { mgr.initialize(req).await })
}
},
acp::on_receive_request!(),
)
.on_receive_request(
{
let mgr = manager.clone();
async move |req: AuthenticateRequest, responder, cx| {
let mgr = mgr.clone();
let cx_for_call = cx.clone();
spawn_task(&cx, responder, async move { mgr.authenticate(req, &cx_for_call).await })
}
},
acp::on_receive_request!(),
)
.on_receive_request(
{
let mgr = manager.clone();
async move |req: NewSessionRequest, responder, cx| {
let mgr = mgr.clone();
let cx_for_call = cx.clone();
spawn_task(&cx, responder, async move { mgr.new_session(req, &cx_for_call).await })
}
},
acp::on_receive_request!(),
)
.on_receive_request(
{
let mgr = manager.clone();
async move |req: ListSessionsRequest, responder, cx| {
let mgr = mgr.clone();
spawn_task(&cx, responder, async move { mgr.list_sessions(&req) })
}
},
acp::on_receive_request!(),
)
.on_receive_request(
{
let mgr = manager.clone();
async move |req: LoadSessionRequest, responder, cx| {
let mgr = mgr.clone();
let cx_for_call = cx.clone();
spawn_task(&cx, responder, async move { mgr.load_session(req, &cx_for_call).await })
}
},
acp::on_receive_request!(),
)
.on_receive_request(
{
let mgr = manager.clone();
async move |req: PromptRequest, responder, cx| {
let mgr = mgr.clone();
spawn_task(&cx, responder, async move { mgr.prompt(req).await })
}
},
acp::on_receive_request!(),
)
.on_receive_request(
{
let mgr = manager.clone();
async move |req: SetSessionConfigOptionRequest, responder, cx| {
let mgr = mgr.clone();
spawn_task(&cx, responder, async move { mgr.set_session_config_option(req).await })
}
},
acp::on_receive_request!(),
)
.on_receive_notification(
{
let mgr = manager.clone();
async move |notif: CancelNotification, _cx| {
let _ = mgr.cancel(notif).await;
Ok(())
}
},
acp::on_receive_notification!(),
)
.on_receive_notification(
{
async move |req: McpRequest, _cx| {
let _ = manager.on_mcp_request(req).await;
Ok(())
}
},
acp::on_receive_notification!(),
)
}
fn spawn_task<T, U>(cx: &ConnectionTo<Client>, responder: Responder<T>, future: U) -> Result<(), acp::Error>
where
T: JsonRpcResponse + Send + 'static,
U: Future<Output = Result<T, acp::Error>> + Send + 'static,
{
cx.spawn(async move {
if let Err(e) = responder.respond_with_result(future.await) {
tracing::warn!("failed to send ACP response: {e:?}");
}
Ok(())
})
}