Skip to main content

relaycast/
types.rs

1//! Type definitions for the RelayCast SDK.
2
3use serde::{Deserialize, Serialize};
4
5// === API Response Envelope ===
6
7#[derive(Debug, Deserialize)]
8pub struct ApiResponse<T> {
9    pub ok: bool,
10    pub data: Option<T>,
11    pub error: Option<ApiErrorInfo>,
12    pub cursor: Option<Cursor>,
13}
14
15#[derive(Debug, Deserialize)]
16pub struct ApiErrorInfo {
17    pub code: String,
18    pub message: String,
19}
20
21#[derive(Debug, Deserialize)]
22pub struct Cursor {
23    pub next: Option<String>,
24    pub has_more: bool,
25}
26
27// === Workspace ===
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct Workspace {
31    pub id: String,
32    pub name: String,
33    pub api_key_hash: String,
34    pub system_prompt: Option<String>,
35    pub plan: String,
36    pub created_at: String,
37    pub metadata: serde_json::Map<String, serde_json::Value>,
38}
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct CreateWorkspaceResponse {
42    pub workspace_id: String,
43    pub api_key: String,
44    pub created_at: String,
45}
46
47#[derive(Debug, Clone, Serialize, Default)]
48pub struct UpdateWorkspaceRequest {
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub name: Option<String>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub system_prompt: Option<String>,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
56pub struct SystemPrompt {
57    pub prompt: String,
58    pub is_default: bool,
59}
60
61#[derive(Debug, Clone, Serialize, Default)]
62pub struct SetSystemPromptRequest {
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub prompt: Option<String>,
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub reset: Option<bool>,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct WorkspaceStreamConfig {
71    pub enabled: bool,
72    pub default_enabled: bool,
73    #[serde(rename = "override")]
74    pub override_value: Option<bool>,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct WorkspaceStats {
79    pub agents: AgentStats,
80    pub messages: MessageStats,
81    pub channels: ChannelStats,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
85pub struct AgentStats {
86    pub total: i64,
87    pub online: i64,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
91pub struct MessageStats {
92    pub total: i64,
93    pub today: i64,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct ChannelStats {
98    pub total: i64,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct ActivityItem {
103    #[serde(rename = "type")]
104    pub item_type: String,
105    pub id: String,
106    pub channel_name: Option<String>,
107    pub conversation_id: Option<String>,
108    pub agent_name: String,
109    pub text: String,
110    pub created_at: String,
111}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
114pub struct WorkspaceDmLastMessage {
115    pub text: String,
116    pub agent_name: String,
117    pub created_at: String,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct WorkspaceDmConversation {
122    pub id: String,
123    #[serde(rename = "type")]
124    pub dm_type: String,
125    pub participants: Vec<String>,
126    pub last_message: Option<WorkspaceDmLastMessage>,
127    pub message_count: i64,
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
131pub struct WorkspaceDmMessage {
132    pub id: String,
133    pub agent_id: String,
134    pub agent_name: String,
135    pub text: String,
136    pub created_at: String,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct TokenRotateResponse {
141    pub name: String,
142    pub token: String,
143}
144
145// === Agents ===
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct Agent {
149    pub id: String,
150    pub workspace_id: String,
151    pub name: String,
152    #[serde(rename = "type")]
153    pub agent_type: String,
154    pub token_hash: String,
155    pub status: String,
156    pub persona: Option<String>,
157    pub metadata: serde_json::Map<String, serde_json::Value>,
158    pub created_at: String,
159    pub last_seen: String,
160}
161
162#[derive(Debug, Clone, Serialize)]
163pub struct CreateAgentRequest {
164    pub name: String,
165    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
166    pub agent_type: Option<String>,
167    #[serde(skip_serializing_if = "Option::is_none")]
168    pub persona: Option<String>,
169    #[serde(skip_serializing_if = "Option::is_none")]
170    pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct CreateAgentResponse {
175    pub id: String,
176    pub name: String,
177    pub token: String,
178    pub status: String,
179    pub created_at: String,
180}
181
182#[derive(Debug, Clone, Serialize, Default)]
183pub struct UpdateAgentRequest {
184    #[serde(skip_serializing_if = "Option::is_none")]
185    pub status: Option<String>,
186    #[serde(skip_serializing_if = "Option::is_none")]
187    pub persona: Option<String>,
188    #[serde(skip_serializing_if = "Option::is_none")]
189    pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct AgentPresenceInfo {
194    pub agent_id: String,
195    pub agent_name: String,
196    pub status: String,
197}
198
199#[derive(Debug, Clone, Serialize)]
200pub struct SpawnAgentRequest {
201    pub name: String,
202    pub cli: String,
203    pub task: String,
204    #[serde(skip_serializing_if = "Option::is_none")]
205    pub channel: Option<String>,
206    #[serde(skip_serializing_if = "Option::is_none")]
207    pub persona: Option<String>,
208    #[serde(skip_serializing_if = "Option::is_none")]
209    pub metadata: Option<serde_json::Value>,
210}
211
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub struct SpawnAgentResponse {
214    pub id: String,
215    pub name: String,
216    pub token: String,
217    pub cli: String,
218    pub task: String,
219    pub channel: Option<String>,
220    pub status: String,
221    pub created_at: String,
222    pub already_existed: bool,
223}
224
225#[derive(Debug, Clone, Serialize)]
226pub struct ReleaseAgentRequest {
227    pub name: String,
228    #[serde(skip_serializing_if = "Option::is_none")]
229    pub reason: Option<String>,
230    #[serde(skip_serializing_if = "Option::is_none")]
231    pub delete_agent: Option<bool>,
232}
233
234#[derive(Debug, Clone, Serialize, Deserialize)]
235pub struct ReleaseAgentResponse {
236    pub name: String,
237    pub released: bool,
238    pub deleted: bool,
239    pub reason: Option<String>,
240}
241
242#[derive(Debug, Clone, Default)]
243pub struct AgentListQuery {
244    pub status: Option<String>,
245}
246
247// === Channels ===
248
249#[derive(Debug, Clone, Serialize, Deserialize)]
250pub struct Channel {
251    pub id: String,
252    pub workspace_id: String,
253    pub name: String,
254    pub channel_type: i64,
255    pub topic: Option<String>,
256    #[serde(default)]
257    pub metadata: serde_json::Map<String, serde_json::Value>,
258    pub created_by: Option<String>,
259    pub created_at: String,
260    pub is_archived: bool,
261    pub member_count: Option<i64>,
262}
263
264#[derive(Debug, Clone, Serialize)]
265pub struct CreateChannelRequest {
266    pub name: String,
267    #[serde(skip_serializing_if = "Option::is_none")]
268    pub topic: Option<String>,
269    #[serde(skip_serializing_if = "Option::is_none")]
270    pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
271}
272
273#[derive(Debug, Clone, Serialize, Default)]
274pub struct UpdateChannelRequest {
275    #[serde(skip_serializing_if = "Option::is_none")]
276    pub topic: Option<String>,
277    #[serde(skip_serializing_if = "Option::is_none")]
278    pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
279}
280
281#[derive(Debug, Clone, Serialize, Deserialize)]
282pub struct ChannelMemberInfo {
283    pub agent_id: String,
284    pub agent_name: String,
285    pub role: String,
286    pub joined_at: String,
287}
288
289#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct ChannelWithMembers {
291    #[serde(flatten)]
292    pub channel: Channel,
293    pub members: Vec<ChannelMemberInfo>,
294}
295
296// === Messages ===
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
299pub struct FileAttachment {
300    pub file_id: String,
301    pub filename: String,
302    #[serde(alias = "contentType")]
303    pub content_type: String,
304    #[serde(alias = "size")]
305    pub size_bytes: i64,
306}
307
308#[derive(Debug, Clone, Serialize, Deserialize)]
309pub struct MessageBlock {
310    #[serde(rename = "type")]
311    pub block_type: String,
312    #[serde(flatten)]
313    pub data: serde_json::Value,
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize)]
317pub struct ReactionGroup {
318    pub emoji: String,
319    pub count: i64,
320    pub agents: Vec<String>,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
324#[serde(rename_all = "lowercase")]
325pub enum MessageInjectionMode {
326    Wait,
327    Steer,
328}
329
330#[derive(Debug, Clone, Serialize, Deserialize)]
331pub struct MessageWithMeta {
332    pub id: String,
333    pub agent_name: String,
334    pub agent_id: String,
335    pub text: String,
336    pub blocks: Option<Vec<MessageBlock>>,
337    #[serde(default)]
338    pub metadata: serde_json::Map<String, serde_json::Value>,
339    #[serde(default)]
340    pub attachments: Vec<FileAttachment>,
341    pub created_at: String,
342    #[serde(default)]
343    pub reply_count: i64,
344    #[serde(default)]
345    pub reactions: Vec<ReactionGroup>,
346    #[serde(default)]
347    pub read_by_count: i64,
348    #[serde(default)]
349    pub injection_mode: Option<MessageInjectionMode>,
350}
351
352#[derive(Debug, Clone, Serialize)]
353pub struct PostMessageRequest {
354    pub text: String,
355    #[serde(skip_serializing_if = "Option::is_none")]
356    pub blocks: Option<Vec<MessageBlock>>,
357    #[serde(skip_serializing_if = "Option::is_none")]
358    pub attachments: Option<Vec<String>>,
359    #[serde(skip_serializing_if = "Option::is_none")]
360    pub data: Option<serde_json::Map<String, serde_json::Value>>,
361    #[serde(skip_serializing_if = "Option::is_none")]
362    pub mode: Option<MessageInjectionMode>,
363}
364
365#[derive(Debug, Clone, Serialize)]
366pub struct ThreadReplyRequest {
367    pub text: String,
368    #[serde(skip_serializing_if = "Option::is_none")]
369    pub blocks: Option<Vec<MessageBlock>>,
370    #[serde(skip_serializing_if = "Option::is_none")]
371    pub data: Option<serde_json::Map<String, serde_json::Value>>,
372}
373
374#[derive(Debug, Clone, Default)]
375pub struct MessageListQuery {
376    pub limit: Option<i32>,
377    pub before: Option<String>,
378    pub after: Option<String>,
379}
380
381#[derive(Debug, Clone, Serialize, Deserialize)]
382pub struct ThreadResponse {
383    pub parent: MessageWithMeta,
384    pub replies: Vec<MessageWithMeta>,
385}
386
387// === DMs ===
388
389#[derive(Debug, Clone, Serialize)]
390pub struct SendDmRequest {
391    pub to: String,
392    pub text: String,
393    #[serde(skip_serializing_if = "Option::is_none")]
394    pub attachments: Option<Vec<String>>,
395    #[serde(skip_serializing_if = "Option::is_none")]
396    pub mode: Option<MessageInjectionMode>,
397}
398
399#[derive(Debug, Clone, Serialize)]
400pub struct CreateGroupDmRequest {
401    pub participants: Vec<String>,
402    #[serde(skip_serializing_if = "Option::is_none")]
403    pub name: Option<String>,
404    pub text: String,
405}
406
407#[derive(Debug, Clone, Serialize, Deserialize)]
408pub struct DmConversationSummary {
409    pub id: String,
410    #[serde(rename = "type")]
411    pub dm_type: String,
412    pub name: Option<String>,
413    #[serde(default, deserialize_with = "deserialize_dm_participants")]
414    pub participants: Vec<String>,
415    #[serde(default, deserialize_with = "deserialize_dm_last_message")]
416    pub last_message: Option<String>,
417    pub unread_count: i64,
418}
419
420#[derive(Debug, Clone, Serialize, Deserialize)]
421pub struct DmSendResponse {
422    pub conversation_id: String,
423    pub message: DmEventPayload,
424    pub created_at: String,
425}
426
427#[derive(Debug, Clone, Serialize, Deserialize)]
428pub struct GroupDmParticipantRef {
429    pub agent_id: String,
430}
431
432#[derive(Debug, Clone, Serialize, Deserialize)]
433pub struct GroupDmConversationResponse {
434    pub id: String,
435    pub channel_id: String,
436    pub dm_type: String,
437    pub name: Option<String>,
438    pub participants: Vec<GroupDmParticipantRef>,
439    pub created_at: String,
440}
441
442#[derive(Debug, Clone, Serialize, Deserialize)]
443pub struct GroupDmMessageResponse {
444    pub conversation_id: String,
445    pub message: DmEventPayload,
446    pub created_at: String,
447}
448
449#[derive(Debug, Clone, Serialize, Deserialize)]
450pub struct GroupDmParticipantResponse {
451    pub conversation_id: String,
452    pub agent: String,
453    pub already_member: bool,
454}
455
456#[derive(Debug, Clone, Deserialize)]
457#[serde(untagged)]
458enum DmParticipantValue {
459    Name(String),
460    Object {
461        agent_name: Option<String>,
462        agent_id: Option<String>,
463    },
464}
465
466fn deserialize_dm_participants<'de, D>(
467    deserializer: D,
468) -> std::result::Result<Vec<String>, D::Error>
469where
470    D: serde::Deserializer<'de>,
471{
472    let raw = Vec::<DmParticipantValue>::deserialize(deserializer)?;
473    Ok(raw
474        .into_iter()
475        .filter_map(|item| match item {
476            DmParticipantValue::Name(name) if !name.is_empty() => Some(name),
477            DmParticipantValue::Object {
478                agent_name: Some(name),
479                ..
480            } if !name.is_empty() => Some(name),
481            DmParticipantValue::Object {
482                agent_id: Some(id), ..
483            } if !id.is_empty() => Some(id),
484            _ => None,
485        })
486        .collect())
487}
488
489#[derive(Debug, Clone, Deserialize)]
490#[serde(untagged)]
491enum DmLastMessageValue {
492    Text(String),
493    Object {
494        text: Option<String>,
495        body: Option<String>,
496    },
497}
498
499fn deserialize_dm_last_message<'de, D>(
500    deserializer: D,
501) -> std::result::Result<Option<String>, D::Error>
502where
503    D: serde::Deserializer<'de>,
504{
505    let raw = Option::<DmLastMessageValue>::deserialize(deserializer)?;
506    Ok(match raw {
507        Some(DmLastMessageValue::Text(text)) if !text.is_empty() => Some(text),
508        Some(DmLastMessageValue::Object {
509            text: Some(text), ..
510        }) if !text.is_empty() => Some(text),
511        Some(DmLastMessageValue::Object {
512            body: Some(body), ..
513        }) if !body.is_empty() => Some(body),
514        _ => None,
515    })
516}
517
518// === Search ===
519
520#[derive(Debug, Clone, Default)]
521pub struct SearchOptions {
522    pub channel: Option<String>,
523    pub from: Option<String>,
524    pub limit: Option<i32>,
525    pub before: Option<String>,
526    pub after: Option<String>,
527}
528
529// === Inbox ===
530
531#[derive(Debug, Clone, Serialize, Deserialize)]
532pub struct UnreadChannel {
533    pub channel_name: String,
534    pub unread_count: i64,
535}
536
537#[derive(Debug, Clone, Serialize, Deserialize)]
538pub struct InboxMention {
539    pub id: String,
540    pub channel_name: String,
541    pub agent_name: String,
542    pub text: String,
543    pub created_at: String,
544}
545
546#[derive(Debug, Clone, Serialize, Deserialize)]
547pub struct UnreadDm {
548    pub conversation_id: String,
549    pub from: String,
550    pub unread_count: i64,
551    pub last_message: Option<String>,
552}
553
554#[derive(Debug, Clone, Serialize, Deserialize)]
555pub struct InboxResponse {
556    pub unread_channels: Vec<UnreadChannel>,
557    pub mentions: Vec<InboxMention>,
558    pub unread_dms: Vec<UnreadDm>,
559}
560
561// === Read Receipts ===
562
563#[derive(Debug, Clone, Serialize, Deserialize)]
564pub struct ReaderInfo {
565    pub agent_name: String,
566    pub agent_id: String,
567    pub read_at: String,
568}
569
570#[derive(Debug, Clone, Serialize, Deserialize)]
571pub struct ChannelReadStatus {
572    pub agent_name: String,
573    pub last_read_id: Option<String>,
574    pub last_read_at: Option<String>,
575}
576
577// === Files ===
578
579#[derive(Debug, Clone, Serialize)]
580pub struct UploadRequest {
581    pub filename: String,
582    pub content_type: String,
583    pub size_bytes: i64,
584}
585
586#[derive(Debug, Clone, Serialize, Deserialize)]
587pub struct UploadResponse {
588    pub file_id: String,
589    pub upload_url: String,
590    pub expires_at: String,
591}
592
593#[derive(Debug, Clone, Serialize, Deserialize)]
594pub struct FileInfo {
595    pub file_id: String,
596    pub filename: String,
597    pub content_type: String,
598    pub size: i64,
599    pub url: String,
600    pub uploaded_by: String,
601    pub created_at: String,
602}
603
604#[derive(Debug, Clone, Default)]
605pub struct FileListOptions {
606    pub uploaded_by: Option<String>,
607    pub limit: Option<i32>,
608}
609
610// === Webhooks ===
611
612#[derive(Debug, Clone, Serialize)]
613pub struct CreateWebhookRequest {
614    pub name: String,
615    pub channel: String,
616}
617
618#[derive(Debug, Clone, Serialize, Deserialize)]
619pub struct CreateWebhookResponse {
620    pub webhook_id: String,
621    pub name: String,
622    pub channel: String,
623    pub url: String,
624    pub created_at: String,
625}
626
627#[derive(Debug, Clone, Serialize, Deserialize)]
628pub struct Webhook {
629    pub id: String,
630    pub workspace_id: String,
631    pub name: String,
632    pub channel_id: String,
633    pub channel_name: String,
634    pub url: String,
635    pub created_by: Option<String>,
636    pub created_at: String,
637    pub is_active: bool,
638}
639
640#[derive(Debug, Clone, Serialize, Default)]
641pub struct WebhookTriggerRequest {
642    #[serde(skip_serializing_if = "Option::is_none")]
643    pub text: Option<String>,
644    #[serde(skip_serializing_if = "Option::is_none")]
645    pub blocks: Option<Vec<serde_json::Value>>,
646    #[serde(skip_serializing_if = "Option::is_none")]
647    pub source: Option<String>,
648    #[serde(skip_serializing_if = "Option::is_none")]
649    pub payload: Option<serde_json::Map<String, serde_json::Value>>,
650}
651
652#[derive(Debug, Clone, Serialize, Deserialize)]
653pub struct WebhookTriggerResponse {
654    pub message_id: String,
655    pub channel: String,
656    pub text: String,
657    pub created_at: String,
658}
659
660// === Subscriptions ===
661
662#[derive(Debug, Clone, Serialize, Deserialize)]
663pub struct SubscriptionFilter {
664    pub channel: Option<String>,
665    pub mentions: Option<String>,
666}
667
668#[derive(Debug, Clone, Serialize, Deserialize)]
669pub struct EventSubscription {
670    pub id: String,
671    pub workspace_id: String,
672    pub events: Vec<String>,
673    pub filter: Option<SubscriptionFilter>,
674    pub url: String,
675    pub secret: Option<String>,
676    pub is_active: bool,
677    pub created_at: String,
678}
679
680#[derive(Debug, Clone, Serialize)]
681pub struct CreateSubscriptionRequest {
682    pub events: Vec<String>,
683    #[serde(skip_serializing_if = "Option::is_none")]
684    pub filter: Option<SubscriptionFilter>,
685    pub url: String,
686    #[serde(skip_serializing_if = "Option::is_none")]
687    pub secret: Option<String>,
688}
689
690#[derive(Debug, Clone, Serialize, Deserialize)]
691pub struct CreateSubscriptionResponse {
692    pub id: String,
693    pub events: Vec<String>,
694    pub filter: Option<SubscriptionFilter>,
695    pub url: String,
696    pub is_active: bool,
697    pub created_at: String,
698}
699
700// === Commands ===
701
702#[derive(Debug, Clone, Serialize, Deserialize)]
703pub struct CommandParameter {
704    pub name: String,
705    pub description: Option<String>,
706    #[serde(rename = "type")]
707    pub parameter_type: String,
708    pub required: Option<bool>,
709}
710
711#[derive(Debug, Clone, Serialize)]
712pub struct CreateCommandRequest {
713    pub command: String,
714    pub description: String,
715    pub handler_agent: String,
716    #[serde(skip_serializing_if = "Option::is_none")]
717    pub parameters: Option<Vec<CommandParameter>>,
718}
719
720#[derive(Debug, Clone, Serialize, Deserialize)]
721pub struct CreateCommandResponse {
722    pub id: String,
723    pub command: String,
724    pub description: String,
725    pub handler_agent: String,
726    pub parameters: Vec<CommandParameter>,
727    pub created_at: String,
728}
729
730#[derive(Debug, Clone, Serialize, Deserialize)]
731pub struct AgentCommand {
732    pub id: String,
733    pub workspace_id: String,
734    pub command: String,
735    pub description: String,
736    pub handler_agent_id: String,
737    pub handler_agent_name: String,
738    pub parameters: Vec<CommandParameter>,
739    pub created_at: String,
740    pub is_active: bool,
741}
742
743#[derive(Debug, Clone, Serialize)]
744pub struct InvokeCommandRequest {
745    pub channel: String,
746    #[serde(skip_serializing_if = "Option::is_none")]
747    pub args: Option<String>,
748    #[serde(skip_serializing_if = "Option::is_none")]
749    pub parameters: Option<serde_json::Map<String, serde_json::Value>>,
750}
751
752#[derive(Debug, Clone, Serialize, Deserialize)]
753pub struct CommandInvocation {
754    pub id: String,
755    pub command: String,
756    pub channel: String,
757    pub invoked_by: String,
758    pub args: Option<String>,
759    pub parameters: Option<serde_json::Map<String, serde_json::Value>>,
760    pub response_message_id: Option<String>,
761    pub created_at: String,
762}
763
764// === WebSocket Events ===
765
766#[derive(Debug, Clone, Serialize, Deserialize)]
767pub struct MessageEventPayload {
768    pub id: String,
769    #[serde(default)]
770    pub agent_id: Option<String>,
771    pub agent_name: String,
772    pub text: String,
773    pub attachments: Vec<FileAttachment>,
774    #[serde(default)]
775    pub injection_mode: Option<MessageInjectionMode>,
776}
777
778#[derive(Debug, Clone, Serialize, Deserialize)]
779pub struct MessageUpdatedPayload {
780    pub id: String,
781    #[serde(default)]
782    pub agent_id: Option<String>,
783    pub agent_name: String,
784    pub text: String,
785}
786
787#[derive(Debug, Clone, Serialize, Deserialize)]
788pub struct ThreadReplyPayload {
789    pub id: String,
790    #[serde(default)]
791    pub agent_id: Option<String>,
792    pub agent_name: String,
793    pub text: String,
794}
795
796#[derive(Debug, Clone, Serialize, Deserialize)]
797pub struct DmEventPayload {
798    pub id: String,
799    pub agent_id: String,
800    pub agent_name: String,
801    pub text: String,
802    #[serde(default)]
803    pub injection_mode: Option<MessageInjectionMode>,
804}
805
806#[derive(Debug, Clone, Serialize, Deserialize)]
807pub struct AgentEventPayload {
808    pub name: String,
809}
810
811#[derive(Debug, Clone, Serialize, Deserialize)]
812pub struct ChannelEventPayload {
813    pub name: String,
814    pub topic: Option<String>,
815}
816
817#[derive(Debug, Clone, Serialize, Deserialize)]
818pub struct ChannelArchivedPayload {
819    pub name: String,
820}
821
822#[derive(Debug, Clone, Serialize, Deserialize)]
823pub struct FileEventPayload {
824    pub file_id: String,
825    pub filename: String,
826    pub uploaded_by: String,
827}
828
829#[derive(Debug, Clone, Serialize, Deserialize)]
830pub struct WebhookMessagePayload {
831    pub id: String,
832    pub text: String,
833    pub source: Option<String>,
834}
835
836#[derive(Debug, Clone, Serialize, Deserialize)]
837#[serde(tag = "type")]
838pub enum WsEvent {
839    #[serde(rename = "message.created")]
840    MessageCreated(MessageCreatedEvent),
841    #[serde(rename = "message.updated")]
842    MessageUpdated(MessageUpdatedEvent),
843    #[serde(rename = "thread.reply")]
844    ThreadReply(ThreadReplyEvent),
845    #[serde(rename = "reaction.added")]
846    ReactionAdded(ReactionAddedEvent),
847    #[serde(rename = "reaction.removed")]
848    ReactionRemoved(ReactionRemovedEvent),
849    #[serde(rename = "dm.received")]
850    DmReceived(DmReceivedEvent),
851    #[serde(rename = "group_dm.received")]
852    GroupDmReceived(GroupDmReceivedEvent),
853    #[serde(rename = "agent.online")]
854    AgentOnline(AgentOnlineEvent),
855    #[serde(rename = "agent.offline")]
856    AgentOffline(AgentOfflineEvent),
857    #[serde(rename = "agent.spawn_requested")]
858    AgentSpawnRequested(AgentSpawnRequestedEvent),
859    #[serde(rename = "agent.release_requested")]
860    AgentReleaseRequested(AgentReleaseRequestedEvent),
861    #[serde(rename = "channel.created")]
862    ChannelCreated(ChannelCreatedEvent),
863    #[serde(rename = "channel.updated")]
864    ChannelUpdated(ChannelUpdatedEvent),
865    #[serde(rename = "channel.archived")]
866    ChannelArchived(ChannelArchivedEvent),
867    #[serde(rename = "member.joined")]
868    MemberJoined(MemberJoinedEvent),
869    #[serde(rename = "member.left")]
870    MemberLeft(MemberLeftEvent),
871    #[serde(rename = "message.read")]
872    MessageRead(MessageReadEvent),
873    #[serde(rename = "file.uploaded")]
874    FileUploaded(FileUploadedEvent),
875    #[serde(rename = "webhook.received")]
876    WebhookReceived(WebhookReceivedEvent),
877    #[serde(rename = "command.invoked")]
878    CommandInvoked(CommandInvokedEvent),
879    #[serde(rename = "pong")]
880    Pong,
881    #[serde(other)]
882    Unknown,
883}
884
885#[derive(Debug, Clone, Serialize, Deserialize)]
886pub struct MessageCreatedEvent {
887    pub channel: String,
888    pub message: MessageEventPayload,
889}
890
891#[derive(Debug, Clone, Serialize, Deserialize)]
892pub struct MessageUpdatedEvent {
893    pub channel: String,
894    pub message: MessageUpdatedPayload,
895}
896
897#[derive(Debug, Clone, Serialize, Deserialize)]
898pub struct ThreadReplyEvent {
899    #[serde(default)]
900    pub channel: Option<String>,
901    pub parent_id: String,
902    pub message: ThreadReplyPayload,
903}
904
905#[derive(Debug, Clone, Serialize, Deserialize)]
906pub struct ReactionAddedEvent {
907    pub message_id: String,
908    pub emoji: String,
909    pub agent_name: String,
910}
911
912#[derive(Debug, Clone, Serialize, Deserialize)]
913pub struct ReactionRemovedEvent {
914    pub message_id: String,
915    pub emoji: String,
916    pub agent_name: String,
917}
918
919#[derive(Debug, Clone, Serialize, Deserialize)]
920pub struct DmReceivedEvent {
921    pub conversation_id: String,
922    pub message: DmEventPayload,
923}
924
925#[derive(Debug, Clone, Serialize, Deserialize)]
926pub struct GroupDmReceivedEvent {
927    pub conversation_id: String,
928    pub message: DmEventPayload,
929}
930
931#[derive(Debug, Clone, Serialize, Deserialize)]
932pub struct AgentOnlineEvent {
933    pub agent: AgentEventPayload,
934}
935
936#[derive(Debug, Clone, Serialize, Deserialize)]
937pub struct AgentOfflineEvent {
938    pub agent: AgentEventPayload,
939}
940
941#[derive(Debug, Clone, Serialize, Deserialize)]
942pub struct AgentSpawnRequestedEvent {
943    pub agent: AgentSpawnRequestedPayload,
944}
945
946#[derive(Debug, Clone, Serialize, Deserialize)]
947pub struct AgentSpawnRequestedPayload {
948    pub name: String,
949    pub cli: String,
950    pub task: String,
951    pub channel: Option<String>,
952    pub already_existed: bool,
953}
954
955#[derive(Debug, Clone, Serialize, Deserialize)]
956pub struct AgentReleaseRequestedEvent {
957    pub agent: AgentEventPayload,
958    pub reason: Option<String>,
959    pub deleted: bool,
960}
961
962#[derive(Debug, Clone, Serialize, Deserialize)]
963pub struct ChannelCreatedEvent {
964    pub channel: ChannelEventPayload,
965}
966
967#[derive(Debug, Clone, Serialize, Deserialize)]
968pub struct ChannelUpdatedEvent {
969    pub channel: ChannelEventPayload,
970}
971
972#[derive(Debug, Clone, Serialize, Deserialize)]
973pub struct ChannelArchivedEvent {
974    pub channel: ChannelArchivedPayload,
975}
976
977#[derive(Debug, Clone, Serialize, Deserialize)]
978pub struct MemberJoinedEvent {
979    pub channel: String,
980    pub agent_name: String,
981}
982
983#[derive(Debug, Clone, Serialize, Deserialize)]
984pub struct MemberLeftEvent {
985    pub channel: String,
986    pub agent_name: String,
987}
988
989#[derive(Debug, Clone, Serialize, Deserialize)]
990pub struct MessageReadEvent {
991    pub message_id: String,
992    pub agent_name: String,
993    pub read_at: String,
994}
995
996#[derive(Debug, Clone, Serialize, Deserialize)]
997pub struct FileUploadedEvent {
998    pub file: FileEventPayload,
999}
1000
1001#[derive(Debug, Clone, Serialize, Deserialize)]
1002pub struct WebhookReceivedEvent {
1003    pub webhook_id: String,
1004    pub channel: String,
1005    pub message: WebhookMessagePayload,
1006}
1007
1008#[derive(Debug, Clone, Serialize, Deserialize)]
1009pub struct CommandInvokedEvent {
1010    pub command: String,
1011    pub channel: String,
1012    pub invoked_by: String,
1013    pub handler_agent_id: String,
1014    pub args: Option<String>,
1015    pub parameters: Option<serde_json::Map<String, serde_json::Value>>,
1016}