meerkat_mobkit/
console_contracts.rs1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6pub const IDENTITY_STREAM_NAME: &str = "identity";
7pub const ALL_EVENTS_STREAM_NAME: &str = "all_events";
8pub const SYSTEM_EVENT_IDENTITY: &str = "_system";
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
11pub struct ConsoleIdentityEventEnvelope {
12 pub event_id: String,
13 #[serde(default, skip_serializing_if = "Option::is_none")]
14 pub interaction_id: Option<String>,
15 pub identity: String,
16 pub event_type: String,
17 pub timestamp_ms: u64,
18 pub data: Value,
19}
20
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22pub struct ReplayUnavailableError {
23 pub error: String,
24 pub stream: String,
25 pub requested_last_event_id: String,
26 pub latest_event_id: String,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
30pub struct ConsoleInteractionRejectedError {
31 pub code: i64,
32 pub message: String,
33}
34
35#[cfg(test)]
36#[allow(clippy::expect_used)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn console_identity_event_envelope_roundtrips_with_interaction_id() {
42 let original = ConsoleIdentityEventEnvelope {
43 event_id: "evt-1".to_string(),
44 interaction_id: Some("turn-123".to_string()),
45 identity: "identity:luka".to_string(),
46 event_type: "interaction_complete".to_string(),
47 timestamp_ms: 1_717_171_717,
48 data: serde_json::json!({
49 "status": "ok",
50 "tool_call_id": "tool-1"
51 }),
52 };
53
54 let encoded = serde_json::to_value(&original).expect("envelope should serialize");
55 let decoded: ConsoleIdentityEventEnvelope =
56 serde_json::from_value(encoded).expect("envelope should deserialize");
57
58 assert_eq!(decoded, original);
59 }
60
61 #[test]
62 fn console_identity_event_envelope_roundtrips_without_interaction_id() {
63 let original = ConsoleIdentityEventEnvelope {
64 event_id: "evt-2".to_string(),
65 interaction_id: None,
66 identity: "identity:luka".to_string(),
67 event_type: "lease_updated".to_string(),
68 timestamp_ms: 1_717_171_718,
69 data: serde_json::json!({
70 "state": "healthy"
71 }),
72 };
73
74 let encoded = serde_json::to_value(&original).expect("envelope should serialize");
75 let decoded: ConsoleIdentityEventEnvelope =
76 serde_json::from_value(encoded).expect("envelope should deserialize");
77
78 assert_eq!(decoded, original);
79 }
80
81 #[test]
82 fn replay_unavailable_error_roundtrips_through_json() {
83 let original = ReplayUnavailableError {
84 error: "replay_unavailable".to_string(),
85 stream: "identity".to_string(),
86 requested_last_event_id: "evt-1".to_string(),
87 latest_event_id: "evt-9".to_string(),
88 };
89
90 let encoded = serde_json::to_value(&original).expect("replay error should serialize");
91 let decoded: ReplayUnavailableError =
92 serde_json::from_value(encoded).expect("replay error should deserialize");
93
94 assert_eq!(decoded, original);
95 }
96
97 #[test]
98 fn console_interaction_rejected_error_roundtrips_through_json() {
99 let original = ConsoleInteractionRejectedError {
100 code: -32001,
101 message: "unknown identity".to_string(),
102 };
103
104 let encoded = serde_json::to_value(&original).expect("rejection error should serialize");
105 let decoded: ConsoleInteractionRejectedError =
106 serde_json::from_value(encoded).expect("rejection error should deserialize");
107
108 assert_eq!(decoded, original);
109 }
110}