a2a_rs/port/message_handler.rs
1//! Message handling port definitions
2
3use async_trait::async_trait;
4
5use crate::{
6 domain::{A2AError, Message, Task},
7 port::RequestContext,
8};
9
10#[async_trait]
11/// An async trait for handling message processing operations
12pub trait AsyncMessageHandler: Send + Sync {
13 /// Process a message for a specific task.
14 ///
15 /// `ctx` is what the transport knows about the request — the session id the
16 /// caller supplied and the principal it authenticated. A handler that keeps
17 /// per-caller state reads [`RequestContext::caller`]; one that does not can
18 /// ignore it.
19 async fn process_message(
20 &self,
21 task_id: &str,
22 message: &Message,
23 ctx: &RequestContext,
24 ) -> Result<Task, A2AError>;
25
26 /// Validate a message before processing
27 async fn validate_message(&self, message: &Message) -> Result<(), A2AError> {
28 // Default implementation - can be overridden
29 if message.parts.is_empty() {
30 return Err(A2AError::ValidationError {
31 field: "message.parts".to_string(),
32 message: "Message must contain at least one part".to_string(),
33 });
34 }
35 Ok(())
36 }
37
38 /// Transform a message before processing (e.g., for content filtering)
39 async fn transform_message(&self, message: Message) -> Result<Message, A2AError> {
40 // Default implementation - pass through unchanged
41 Ok(message)
42 }
43
44 /// Handle message processing with validation and transformation
45 async fn handle_message_flow(
46 &self,
47 task_id: &str,
48 message: Message,
49 ctx: &RequestContext,
50 ) -> Result<Task, A2AError> {
51 // Validate the message
52 self.validate_message(&message).await?;
53
54 // Transform the message if needed
55 let transformed_message = self.transform_message(message).await?;
56
57 // Process the message
58 self.process_message(task_id, &transformed_message, ctx)
59 .await
60 }
61}