use chrono::{DateTime, Utc};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use systemprompt_identifiers::{AgentName, NotificationStreamId, UserId};
use super::attention::Attention;
use super::kind::NotificationKind;
use super::subject::SubjectRef;
pub const NOTIFICATIONS_CONSUMER: &str = "notifications";
pub const NOTIFICATION_EVENT_VERSION: u32 = 1;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct DirectRecipient {
pub user: UserId,
pub attention: Option<Attention>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct NotificationEvent {
pub kind: NotificationKind,
pub actor: UserId,
pub actor_is_agent: bool,
pub via_agent: Option<AgentName>,
pub subjects: Vec<SubjectRef>,
pub stream: Option<NotificationStreamId>,
pub direct_recipients: Vec<DirectRecipient>,
pub sender_attention: Option<Attention>,
pub title: Option<String>,
pub body: Option<String>,
pub payload: serde_json::Value,
pub occurred_at: DateTime<Utc>,
}
impl NotificationEvent {
#[must_use]
pub const fn new(kind: NotificationKind, actor: UserId, occurred_at: DateTime<Utc>) -> Self {
Self {
kind,
actor,
actor_is_agent: false,
via_agent: None,
subjects: Vec::new(),
stream: None,
direct_recipients: Vec::new(),
sender_attention: None,
title: None,
body: None,
payload: serde_json::Value::Null,
occurred_at,
}
}
#[must_use]
pub const fn with_actor_is_agent(mut self, actor_is_agent: bool) -> Self {
self.actor_is_agent = actor_is_agent;
self
}
#[must_use]
pub fn with_via_agent(mut self, via_agent: AgentName) -> Self {
self.via_agent = Some(via_agent);
self
}
#[must_use]
pub fn with_subject(mut self, subject: SubjectRef) -> Self {
self.subjects.push(subject);
self
}
#[must_use]
pub fn with_subjects(mut self, subjects: impl IntoIterator<Item = SubjectRef>) -> Self {
self.subjects.extend(subjects);
self
}
#[must_use]
pub fn with_stream(mut self, stream: NotificationStreamId) -> Self {
self.stream = Some(stream);
self
}
#[must_use]
pub fn with_direct_recipient(mut self, user: UserId, attention: Option<Attention>) -> Self {
self.direct_recipients
.push(DirectRecipient { user, attention });
self
}
#[must_use]
pub fn with_direct_recipients(
mut self,
recipients: impl IntoIterator<Item = DirectRecipient>,
) -> Self {
self.direct_recipients.extend(recipients);
self
}
#[must_use]
pub const fn with_sender_attention(mut self, attention: Attention) -> Self {
self.sender_attention = Some(attention);
self
}
#[must_use]
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
#[must_use]
pub fn with_body(mut self, body: impl Into<String>) -> Self {
self.body = Some(body.into());
self
}
#[must_use]
pub fn with_payload(mut self, payload: serde_json::Value) -> Self {
self.payload = payload;
self
}
}