Skip to main content

ai_crew_sync/
model.rs

1//! Wire types returned by the MCP tools.
2//!
3//! Timestamps are RFC 3339 strings rather than typed datetimes: the consumer is
4//! a language model, and a plain string is both unambiguous and free of extra
5//! schema dependencies.
6
7use schemars::JsonSchema;
8use serde::Serialize;
9
10pub fn ts(dt: chrono::DateTime<chrono::Utc>) -> String {
11    dt.to_rfc3339_opts(chrono::SecondsFormat::Secs, true)
12}
13
14pub fn ts_opt(dt: Option<chrono::DateTime<chrono::Utc>>) -> Option<String> {
15    dt.map(ts)
16}
17
18#[derive(Debug, Serialize, JsonSchema)]
19pub struct WhoAmI {
20    /// Your agent handle. Other agents address you by this name.
21    pub agent: String,
22    pub agent_id: String,
23    pub team: String,
24    pub team_id: String,
25    /// Number of unread direct messages waiting for you.
26    pub unread_direct_messages: i64,
27    /// Tasks currently claimed by you and not yet completed.
28    pub open_claimed_tasks: i64,
29}
30
31// ------------------------------------------------------------------ agents --
32
33#[derive(Debug, Serialize, JsonSchema)]
34pub struct AgentInfo {
35    pub name: String,
36    pub display_name: Option<String>,
37    /// One of `active`, `idle`, `offline`. `offline` means the presence lease
38    /// expired, i.e. the agent has not sent a heartbeat recently.
39    pub status: String,
40    pub repo: Option<String>,
41    pub branch: Option<String>,
42    /// Free-text description of what this agent is currently doing.
43    pub activity: Option<String>,
44    pub last_seen: Option<String>,
45    pub online: bool,
46}
47
48#[derive(Debug, Serialize, JsonSchema)]
49pub struct AgentList {
50    pub agents: Vec<AgentInfo>,
51    pub online_count: usize,
52}
53
54// -------------------------------------------------------------- messaging --
55
56#[derive(Debug, Serialize, JsonSchema)]
57pub struct ChannelInfo {
58    pub name: String,
59    pub topic: Option<String>,
60    pub message_count: i64,
61    pub created_at: String,
62}
63
64#[derive(Debug, Serialize, JsonSchema)]
65pub struct ChannelList {
66    pub channels: Vec<ChannelInfo>,
67}
68
69#[derive(Debug, Serialize, JsonSchema)]
70pub struct MessageInfo {
71    pub id: i64,
72    pub from: String,
73    /// Channel name for channel messages; `null` for direct messages.
74    pub channel: Option<String>,
75    /// Recipient handle for direct messages; `null` for channel messages.
76    pub to: Option<String>,
77    pub body: String,
78    pub reply_to: Option<i64>,
79    pub metadata: serde_json::Value,
80    /// Files attached to this message; fetch content with get_attachment.
81    pub attachments: Vec<AttachmentMeta>,
82    pub created_at: String,
83}
84
85#[derive(Debug, Serialize, serde::Deserialize, JsonSchema)]
86pub struct AttachmentMeta {
87    /// Pass this id to get_attachment to download the content.
88    pub id: i64,
89    pub filename: String,
90    pub content_type: String,
91    pub size_bytes: i64,
92}
93
94#[derive(Debug, Serialize, JsonSchema)]
95pub struct AttachmentContent {
96    pub id: i64,
97    pub filename: String,
98    pub content_type: String,
99    pub size_bytes: i64,
100    pub uploaded_by: String,
101    pub created_at: String,
102    /// The file content, base64-encoded.
103    pub data_base64: String,
104}
105
106#[derive(Debug, Serialize, JsonSchema)]
107pub struct PostMessageResult {
108    pub message: MessageInfo,
109    /// Handles that can now see this message.
110    pub delivered_to: Vec<String>,
111}
112
113#[derive(Debug, Serialize, JsonSchema)]
114pub struct MessageList {
115    pub messages: Vec<MessageInfo>,
116    /// The scope that was actually read, after normalisation.
117    pub scope: String,
118    /// Read cursor position after this call. Messages at or below this id will
119    /// not be returned again when `only_new` is true.
120    pub cursor: i64,
121    /// True when the result hit `limit` and older/newer messages remain.
122    pub truncated: bool,
123}
124
125// ------------------------------------------------------------------ tasks --
126
127#[derive(Debug, Serialize, JsonSchema)]
128pub struct TaskInfo {
129    pub key: String,
130    pub title: String,
131    pub description: Option<String>,
132    /// One of `open`, `claimed`, `done`, `cancelled`.
133    pub status: String,
134    /// Keys of tasks this one depends on.
135    pub depends_on: Vec<String>,
136    /// True while any dependency is not yet done/cancelled. Blocked tasks
137    /// cannot be claimed.
138    pub blocked: bool,
139    pub claimed_by: Option<String>,
140    pub claimed_at: Option<String>,
141    /// When the current claim expires. After this instant another agent may
142    /// steal the task, so renew the lease if you are still working on it.
143    pub lease_expires_at: Option<String>,
144    /// True when the claim has already lapsed.
145    pub lease_expired: bool,
146    pub result: Option<String>,
147    pub metadata: serde_json::Value,
148    /// Files attached to this task; fetch content with get_attachment.
149    pub attachments: Vec<AttachmentMeta>,
150    pub created_by: Option<String>,
151    pub created_at: String,
152    pub updated_at: String,
153}
154
155#[derive(Debug, Serialize, JsonSchema)]
156pub struct TaskList {
157    pub tasks: Vec<TaskInfo>,
158    pub open: i64,
159    pub claimed: i64,
160}
161
162#[derive(Debug, Serialize, JsonSchema)]
163pub struct ClaimResult {
164    pub claimed: bool,
165    pub task: Option<TaskInfo>,
166    /// Present when `claimed` is false: why the claim did not succeed.
167    pub reason: Option<String>,
168}
169
170#[derive(Debug, Serialize, JsonSchema)]
171pub struct TaskEventInfo {
172    pub event: String,
173    pub agent: Option<String>,
174    pub detail: Option<String>,
175    pub created_at: String,
176}
177
178#[derive(Debug, Serialize, JsonSchema)]
179pub struct TaskDetail {
180    pub task: TaskInfo,
181    pub history: Vec<TaskEventInfo>,
182}
183
184// ------------------------------------------------------------------ notes --
185
186#[derive(Debug, Serialize, JsonSchema)]
187pub struct NoteInfo {
188    pub scope: String,
189    pub key: String,
190    pub value: String,
191    pub tags: Vec<String>,
192    pub updated_by: Option<String>,
193    pub updated_at: String,
194}
195
196#[derive(Debug, Serialize, JsonSchema)]
197pub struct NoteList {
198    pub notes: Vec<NoteInfo>,
199}
200
201#[derive(Debug, Serialize, JsonSchema)]
202pub struct NoteRef {
203    pub scope: String,
204    pub key: String,
205    pub found: bool,
206    pub note: Option<NoteInfo>,
207}
208
209#[derive(Debug, Serialize, JsonSchema)]
210pub struct Ack {
211    pub ok: bool,
212    pub detail: String,
213}
214
215// ------------------------------------------------------------------ locks --
216
217#[derive(Debug, Serialize, JsonSchema)]
218pub struct LockInfo {
219    pub name: String,
220    pub holder: String,
221    pub purpose: Option<String>,
222    pub acquired_at: String,
223    /// When the lock lapses on its own if not renewed.
224    pub expires_at: String,
225}
226
227#[derive(Debug, Serialize, JsonSchema)]
228pub struct LockList {
229    pub locks: Vec<LockInfo>,
230}
231
232#[derive(Debug, Serialize, JsonSchema)]
233pub struct LockResult {
234    pub acquired: bool,
235    pub lock: Option<LockInfo>,
236    /// Present when `acquired` is false: who holds it and until when.
237    pub reason: Option<String>,
238}
239
240// ----------------------------------------------------------------- events --
241
242#[derive(Debug, Serialize, JsonSchema)]
243pub struct WaitEvent {
244    /// One of `message`, `task`, `lock`, `note`.
245    pub kind: String,
246    /// Human-readable one-liner of what happened.
247    pub summary: String,
248}
249
250#[derive(Debug, Serialize, JsonSchema)]
251pub struct WaitResult {
252    /// True when something happened; false when the timeout elapsed quietly.
253    pub woke: bool,
254    pub timed_out: bool,
255    pub events: Vec<WaitEvent>,
256    /// Unread direct messages after the wait — if > 0, call read_messages.
257    pub unread_direct_messages: i64,
258    /// What to do next, e.g. which tool to call to fetch the details.
259    pub suggestion: String,
260}
261
262#[derive(Debug, Serialize, JsonSchema)]
263pub struct AskResult {
264    /// True when the teammate answered before the timeout.
265    pub answered: bool,
266    /// The agent the question was addressed to.
267    pub to: String,
268    /// Id of the question message. On timeout, pass it back as
269    /// `resume_message_id` to keep waiting without re-sending the question.
270    pub question_message_id: i64,
271    /// The answer: their reply to the question, or failing that their first
272    /// direct message to you after it.
273    pub answer: Option<MessageInfo>,
274    /// What to do next.
275    pub suggestion: String,
276}
277
278// ----------------------------------------------------------------- digest --
279
280#[derive(Debug, Serialize, JsonSchema)]
281pub struct DigestMessage {
282    pub from: String,
283    pub body: String,
284    pub at: String,
285}
286
287#[derive(Debug, Serialize, JsonSchema)]
288pub struct DigestChannel {
289    pub name: String,
290    pub message_count: i64,
291    pub last_messages: Vec<DigestMessage>,
292}
293
294#[derive(Debug, Serialize, JsonSchema)]
295pub struct DigestTask {
296    pub key: String,
297    pub title: String,
298    pub status: String,
299    pub claimed_by: Option<String>,
300    pub result: Option<String>,
301    pub updated_at: String,
302}
303
304#[derive(Debug, Serialize, JsonSchema)]
305pub struct DigestNote {
306    pub scope: String,
307    pub key: String,
308    pub updated_by: Option<String>,
309    pub updated_at: String,
310}
311
312#[derive(Debug, Serialize, JsonSchema)]
313pub struct DigestAgent {
314    pub name: String,
315    pub activity: Option<String>,
316    pub last_seen: Option<String>,
317    pub online: bool,
318}
319
320#[derive(Debug, Serialize, JsonSchema)]
321pub struct DigestResult {
322    /// Window covered, in hours.
323    pub hours: i64,
324    pub channels: Vec<DigestChannel>,
325    /// Tasks whose state changed inside the window, newest first.
326    pub tasks_moved: Vec<DigestTask>,
327    pub open_tasks: i64,
328    pub claimed_tasks: i64,
329    pub notes_updated: Vec<DigestNote>,
330    pub agents_seen: Vec<DigestAgent>,
331    pub active_locks: Vec<LockInfo>,
332}