Skip to main content

dakera_client/
events.rs

1//! SSE streaming event types and client support (CE-1).
2//!
3//! ## Usage
4//!
5//! ```rust,no_run
6//! use dakera_client::DakeraClient;
7//! use tokio::sync::mpsc;
8//!
9//! #[tokio::main]
10//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
11//!     let client = DakeraClient::new("http://localhost:3000")?;
12//!
13//!     let mut rx = client.stream_namespace_events("my-ns").await?;
14//!     while let Some(result) = rx.recv().await {
15//!         let event = result?;
16//!         println!("Event: {:?}", event);
17//!     }
18//!     Ok(())
19//! }
20//! ```
21
22use serde::{Deserialize, Serialize};
23
24/// Operation status for [`DakeraEvent::OperationProgress`] events.
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
26#[serde(rename_all = "snake_case")]
27pub enum OpStatus {
28    Pending,
29    Running,
30    Completed,
31    Failed,
32}
33
34/// Vector mutation operation type for [`DakeraEvent::VectorsMutated`] events.
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
36#[serde(rename_all = "snake_case")]
37pub enum VectorMutationOp {
38    Upserted,
39    Deleted,
40}
41
42/// An event received from a Dakera SSE stream.
43///
44/// Mirrors the server-side `DakeraEvent` enum.  Events are delivered over
45/// `GET /v1/namespaces/:ns/events` (namespace-scoped, Read scope) or
46/// `GET /ops/events` (global, Admin scope).
47///
48/// Use [`DakeraClient::stream_namespace_events`] or
49/// [`DakeraClient::stream_global_events`] to subscribe.
50#[derive(Debug, Clone, Serialize, Deserialize)]
51#[serde(tag = "type", rename_all = "snake_case")]
52pub enum DakeraEvent {
53    /// A new namespace was created.
54    NamespaceCreated { namespace: String, dimension: usize },
55
56    /// A namespace was deleted.
57    NamespaceDeleted { namespace: String },
58
59    /// Progress update for a long-running operation (progress: 0–100).
60    OperationProgress {
61        operation_id: String,
62        #[serde(skip_serializing_if = "Option::is_none")]
63        namespace: Option<String>,
64        op_type: String,
65        /// Progress percentage 0–100.
66        progress: u8,
67        status: OpStatus,
68        #[serde(skip_serializing_if = "Option::is_none")]
69        message: Option<String>,
70        /// Unix milliseconds.
71        updated_at: u64,
72    },
73
74    /// A background job changed status.
75    JobProgress {
76        job_id: String,
77        job_type: String,
78        #[serde(skip_serializing_if = "Option::is_none")]
79        namespace: Option<String>,
80        progress: u8,
81        status: String,
82    },
83
84    /// Vectors were upserted or deleted in bulk (threshold: >100 vectors).
85    VectorsMutated {
86        namespace: String,
87        op: VectorMutationOp,
88        count: usize,
89    },
90
91    /// Subscriber fell too far behind — some events were dropped.
92    /// Reconnect to resume the stream.
93    StreamLagged { dropped: u64, hint: String },
94}
95
96/// A memory lifecycle event received from the `GET /v1/events/stream` SSE endpoint (DASH-B).
97///
98/// Use [`DakeraClient::stream_memory_events`] to subscribe.
99#[derive(Debug, Clone, Serialize, Deserialize)]
100pub struct MemoryEvent {
101    pub event_type: String,
102    pub agent_id: String,
103    /// Unix milliseconds.
104    pub timestamp: u64,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub memory_id: Option<String>,
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub content: Option<String>,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub importance: Option<f32>,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub tags: Option<Vec<String>>,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub session_id: Option<String>,
115}
116
117impl DakeraEvent {
118    /// Returns the SSE `event` type string for this event variant.
119    pub fn event_type(&self) -> &'static str {
120        match self {
121            DakeraEvent::NamespaceCreated { .. } => "namespace_created",
122            DakeraEvent::NamespaceDeleted { .. } => "namespace_deleted",
123            DakeraEvent::OperationProgress { .. } => "operation_progress",
124            DakeraEvent::JobProgress { .. } => "job_progress",
125            DakeraEvent::VectorsMutated { .. } => "vectors_mutated",
126            DakeraEvent::StreamLagged { .. } => "stream_lagged",
127        }
128    }
129}