use crate::error::Result;
use crate::message::MessageConverter;
use a2a_rs::domain::{message::Message, task::Task};
use rmcp::{ToolCall, ToolResponse};
use async_trait::async_trait;
use std::sync::Arc;
pub struct A2aToRmcpTransport {
converter: Arc<MessageConverter>,
}
impl A2aToRmcpTransport {
pub fn new(converter: Arc<MessageConverter>) -> Self {
Self { converter }
}
pub async fn convert_message_to_tool_call(&self, msg: &Message, method: &str) -> Result<ToolCall> {
let params = msg.parts.iter()
.find_map(|part| {
if let a2a_rs::domain::message::MessagePart::Data { data, .. } = part {
Some(data.clone())
} else {
None
}
})
.unwrap_or(serde_json::Value::Null);
Ok(ToolCall {
method: method.to_string(),
params,
})
}
pub async fn convert_tool_response_to_message(&self, resp: &ToolResponse) -> Result<Message> {
let mut parts = Vec::new();
parts.push(a2a_rs::domain::message::MessagePart::Data {
data: resp.result.clone(),
mime_type: Some("application/json".to_string()),
});
if let serde_json::Value::String(text) = &resp.result {
parts.push(a2a_rs::domain::message::MessagePart::Text {
text: text.clone()
});
}
Ok(Message {
role: "agent".to_string(),
parts,
})
}
}
#[async_trait]
pub trait A2aToRmcpHandler {
async fn process_a2a_task(&self, task: &Task) -> Result<ToolResponse>;
}