1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::sync::{Arc, Mutex};
use crate::error::AgentError;
use crate::registry::{AgentRef, AgentRegistry};
use crate::types::AgentMessage;
/// A per-agent inbox for receiving messages.
///
/// Wraps a `Vec<AgentMessage>` behind an `Arc<Mutex<_>>` so it can be shared
/// between the agent owner and any senders.
#[derive(Clone)]
pub struct AgentMailbox {
inbox: Arc<Mutex<Vec<AgentMessage>>>,
}
impl AgentMailbox {
/// Create an empty mailbox.
#[must_use]
pub fn new() -> Self {
Self {
inbox: Arc::new(Mutex::new(Vec::new())),
}
}
/// Push a message into the mailbox.
pub fn send(&self, message: AgentMessage) {
self.inbox
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.push(message);
}
/// Take all pending messages, leaving the mailbox empty.
pub fn drain(&self) -> Vec<AgentMessage> {
std::mem::take(
&mut *self
.inbox
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner),
)
}
/// Whether the mailbox has pending messages.
#[must_use]
pub fn has_messages(&self) -> bool {
!self
.inbox
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.is_empty()
}
/// Number of pending messages.
#[must_use]
pub fn len(&self) -> usize {
self.inbox
.lock()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.len()
}
/// Whether the mailbox is empty.
#[must_use]
pub fn is_empty(&self) -> bool {
!self.has_messages()
}
}
impl Default for AgentMailbox {
fn default() -> Self {
Self::new()
}
}
/// Send a message to a named agent via its steering queue.
///
/// Looks up the agent by name in the registry, acquires the lock, and calls
/// `steer(message)` to inject the message into the agent's steering queue.
///
/// # Errors
///
/// Returns [`AgentError::Plugin`] if the agent is not found in the registry.
pub async fn send_to(
registry: &AgentRegistry,
agent_name: &str,
message: AgentMessage,
) -> Result<(), AgentError> {
let agent_ref: AgentRef = registry.get(agent_name).ok_or_else(|| {
AgentError::plugin(
"messaging",
std::io::Error::other(format!("agent not found: {agent_name}")),
)
})?;
agent_ref.lock().await.steer(message);
Ok(())
}