feat(proto): EventKind, EventRecord, MarkReadTarget
This commit is contained in:
@@ -0,0 +1,76 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::ids::{SurfaceId, WorkspaceId};
|
||||||
|
|
||||||
|
/// The subset of activity that lands in the event log.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum EventKind {
|
||||||
|
Done,
|
||||||
|
Wait,
|
||||||
|
Error,
|
||||||
|
Exit,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// One logged event. Workspace name and agent label are denormalized so the
|
||||||
|
/// feed stays displayable after the surface or workspace is closed.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct EventRecord {
|
||||||
|
pub id: u64,
|
||||||
|
pub surface_id: SurfaceId,
|
||||||
|
pub workspace_id: WorkspaceId,
|
||||||
|
pub workspace_name: String,
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub agent_label: Option<String>,
|
||||||
|
pub kind: EventKind,
|
||||||
|
pub ts: u64,
|
||||||
|
pub read: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// What a `mark_read` request targets.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "target", content = "value", rename_all = "snake_case")]
|
||||||
|
pub enum MarkReadTarget {
|
||||||
|
All,
|
||||||
|
Ids(Vec<u64>),
|
||||||
|
Surface(SurfaceId),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn event_kind_serializes_lowercase() {
|
||||||
|
assert_eq!(serde_json::to_string(&EventKind::Done).unwrap(), r#""done""#);
|
||||||
|
assert_eq!(serde_json::to_string(&EventKind::Exit).unwrap(), r#""exit""#);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn event_record_round_trips() {
|
||||||
|
let r = EventRecord {
|
||||||
|
id: 7,
|
||||||
|
surface_id: SurfaceId("s_1".into()),
|
||||||
|
workspace_id: WorkspaceId("w_1".into()),
|
||||||
|
workspace_name: "infra".into(),
|
||||||
|
agent_label: Some("claude".into()),
|
||||||
|
kind: EventKind::Error,
|
||||||
|
ts: 1_700_000_000_000,
|
||||||
|
read: false,
|
||||||
|
};
|
||||||
|
let back: EventRecord = serde_json::from_str(&serde_json::to_string(&r).unwrap()).unwrap();
|
||||||
|
assert_eq!(back, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mark_read_target_variants_serialize() {
|
||||||
|
assert_eq!(serde_json::to_string(&MarkReadTarget::All).unwrap(), r#"{"target":"all"}"#);
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::to_string(&MarkReadTarget::Ids(vec![1, 2])).unwrap(),
|
||||||
|
r#"{"target":"ids","value":[1,2]}"#
|
||||||
|
);
|
||||||
|
let s = MarkReadTarget::Surface(SurfaceId("s_9".into()));
|
||||||
|
assert_eq!(serde_json::to_string(&s).unwrap(), r#"{"target":"surface","value":"s_9"}"#);
|
||||||
|
let back: MarkReadTarget = serde_json::from_str(&serde_json::to_string(&s).unwrap()).unwrap();
|
||||||
|
assert_eq!(back, s);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
pub mod codec;
|
pub mod codec;
|
||||||
|
pub mod event;
|
||||||
pub mod ids;
|
pub mod ids;
|
||||||
pub mod layout;
|
pub mod layout;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
pub mod workspace;
|
pub mod workspace;
|
||||||
|
|
||||||
|
pub use event::{EventKind, EventRecord, MarkReadTarget};
|
||||||
pub use ids::{GroupId, SurfaceId, WorkspaceId};
|
pub use ids::{GroupId, SurfaceId, WorkspaceId};
|
||||||
pub use layout::{LayoutNode, Orient};
|
pub use layout::{LayoutNode, Orient};
|
||||||
pub use message::{Cmd, Envelope, ErrorBody, Evt};
|
pub use message::{Cmd, Envelope, ErrorBody, Evt};
|
||||||
|
|||||||
Reference in New Issue
Block a user