1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4use std::path::PathBuf;
5use uuid::Uuid;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(rename_all = "lowercase")]
9pub enum NotificationStatus {
10 Success,
11 Failure,
12 Partial,
13 Waiting,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct Notification {
18 pub version: u32,
20 pub id: Uuid,
22 pub worktree: PathBuf,
24 pub branch: String,
26 pub status: NotificationStatus,
28 pub summary: String,
30 pub timestamp: DateTime<Utc>,
32 pub agent: String,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
37 pub duration_secs: Option<u64>,
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub commit: Option<String>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub files_changed: Option<Vec<String>>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub stats: Option<FileStats>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub task: Option<String>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub log_file: Option<PathBuf>,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 pub tags: Option<Vec<String>>,
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub custom: Option<HashMap<String, serde_json::Value>>,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct FileStats {
56 pub added: u32,
57 pub removed: u32,
58}
59
60impl Notification {
61 pub fn new(
62 worktree: PathBuf,
63 branch: String,
64 status: NotificationStatus,
65 summary: String,
66 agent: String,
67 ) -> Self {
68 Self {
69 version: 1,
70 id: Uuid::new_v4(),
71 worktree,
72 branch,
73 status,
74 summary,
75 timestamp: Utc::now(),
76 agent,
77 duration_secs: None,
78 commit: None,
79 files_changed: None,
80 stats: None,
81 task: None,
82 log_file: None,
83 tags: None,
84 custom: None,
85 }
86 }
87}