feat(proto): EventKind, EventRecord, MarkReadTarget

This commit is contained in:
2026-06-10 06:49:33 +07:00
parent 36964c9f21
commit fc13e4340c
2 changed files with 78 additions and 0 deletions
+76
View File
@@ -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);
}
}
+2
View File
@@ -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};