substrate_core/mailbox_port.rs
1//! MailboxStore port — durable mailbox and tasklist backed by a concrete store.
2//!
3//! This port is implemented by `store-sqlite`; the core crate only defines the
4//! contract. No IO, no adapter dependencies here.
5//!
6//! The port uses its own mirror types so that `substrate-core` stays free of
7//! any dependency on `a2a` or adapter crates. `store-sqlite` maps between the
8//! `a2a` types and these port-level types internally.
9
10use uuid::Uuid;
11
12/// Opaque task state at the port boundary.
13///
14/// Adapters convert to/from `a2a::TaskState` internally.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum MailboxTaskState {
17 /// Submitted, not yet started.
18 Submitted,
19 /// Actively being worked on.
20 Working,
21 /// Waiting for caller input.
22 InputRequired,
23 /// Finished successfully.
24 Completed,
25 /// Ended in error.
26 Failed,
27 /// Explicitly cancelled.
28 Cancelled,
29}
30
31/// The MailboxStore port: durable mailbox + task list.
32///
33/// Implementations MUST guarantee atomic claim semantics: at most one caller
34/// wins the race to claim a given message (i.e. `Unread → Delivered` is
35/// exclusive).
36pub trait MailboxStore: Send + Sync {
37 /// The message type stored by this implementation.
38 type Msg;
39 /// The task type stored by this implementation.
40 type Task;
41 /// The error type returned by store operations.
42 type Error: std::error::Error + Send + Sync + 'static;
43
44 /// Post a message into the mailbox.
45 fn post(&self, msg: &Self::Msg) -> Result<(), Self::Error>;
46
47 /// Return all unread messages addressed to `to` in `team_id`.
48 fn inbox(&self, team_id: &str, to: &str) -> Result<Vec<Self::Msg>, Self::Error>;
49
50 /// Atomic claim: transition message state from `Unread` to `Delivered`.
51 ///
52 /// Returns `true` iff this caller won the race (SQLite rowcount == 1).
53 fn claim(&self, message_id: Uuid) -> Result<bool, Self::Error>;
54
55 /// Mark a message as `Consumed`.
56 fn consume(&self, message_id: Uuid) -> Result<(), Self::Error>;
57
58 /// Roll back a claim: transition message state from `Delivered` to `Unread`.
59 fn unclaim(&self, message_id: Uuid) -> Result<(), Self::Error>;
60
61 /// Insert a new task.
62 fn task_create(&self, task: &Self::Task) -> Result<(), Self::Error>;
63
64 /// Advance a task's state, optionally recording a note.
65 fn task_update(
66 &self,
67 id: Uuid,
68 state: MailboxTaskState,
69 note: Option<&str>,
70 ) -> Result<(), Self::Error>;
71
72 /// Return all tasks for a team.
73 fn task_list(&self, team_id: &str) -> Result<Vec<Self::Task>, Self::Error>;
74}