ai_agent/services/
notifier.rs1pub const DEFAULT_TITLE: &str = "Claude Code";
7
8#[derive(Debug, Clone)]
9pub struct NotificationOptions {
10 pub message: String,
11 pub title: Option<String>,
12 pub notification_type: String,
13}
14
15impl NotificationOptions {
16 pub fn new(message: impl Into<String>, notification_type: impl Into<String>) -> Self {
17 Self {
18 message: message.into(),
19 title: None,
20 notification_type: notification_type.into(),
21 }
22 }
23
24 pub fn with_title(mut self, title: impl Into<String>) -> Self {
25 self.title = Some(title.into());
26 self
27 }
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum NotificationChannel {
32 Auto,
33 Iterm2,
34 Iterm2WithBell,
35 Kitty,
36 Ghostty,
37 TerminalBell,
38 NotificationsDisabled,
39 None,
40 Error,
41 NoMethodAvailable,
42}
43
44impl NotificationChannel {
45 pub fn from_str(s: &str) -> Self {
46 match s {
47 "auto" => NotificationChannel::Auto,
48 "iterm2" => NotificationChannel::Iterm2,
49 "iterm2_with_bell" => NotificationChannel::Iterm2WithBell,
50 "kitty" => NotificationChannel::Kitty,
51 "ghostty" => NotificationChannel::Ghostty,
52 "terminal_bell" => NotificationChannel::TerminalBell,
53 "notifications_disabled" => NotificationChannel::NotificationsDisabled,
54 _ => NotificationChannel::None,
55 }
56 }
57
58 pub fn as_str(&self) -> &'static str {
59 match self {
60 NotificationChannel::Auto => "auto",
61 NotificationChannel::Iterm2 => "iterm2",
62 NotificationChannel::Iterm2WithBell => "iterm2_with_bell",
63 NotificationChannel::Kitty => "kitty",
64 NotificationChannel::Ghostty => "ghostty",
65 NotificationChannel::TerminalBell => "terminal_bell",
66 NotificationChannel::NotificationsDisabled => "disabled",
67 NotificationChannel::None => "none",
68 NotificationChannel::Error => "error",
69 NotificationChannel::NoMethodAvailable => "no_method_available",
70 }
71 }
72}
73
74pub fn generate_kitty_id() -> u32 {
75 use std::time::{SystemTime, UNIX_EPOCH};
76
77 let nanos = SystemTime::now()
78 .duration_since(UNIX_EPOCH)
79 .unwrap_or_default()
80 .subsec_nanos();
81
82 (nanos % 10000) as u32
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_notification_options() {
91 let opts = NotificationOptions::new("Test message", "test");
92 assert_eq!(opts.message, "Test message");
93 assert_eq!(opts.notification_type, "test");
94 assert!(opts.title.is_none());
95 }
96
97 #[test]
98 fn test_notification_options_with_title() {
99 let opts = NotificationOptions::new("Test message", "test").with_title("Test Title");
100 assert_eq!(opts.title, Some("Test Title".to_string()));
101 }
102
103 #[test]
104 fn test_notification_channel_from_str() {
105 assert_eq!(
106 NotificationChannel::from_str("auto"),
107 NotificationChannel::Auto
108 );
109 assert_eq!(
110 NotificationChannel::from_str("iterm2"),
111 NotificationChannel::Iterm2
112 );
113 assert_eq!(
114 NotificationChannel::from_str("kitty"),
115 NotificationChannel::Kitty
116 );
117 assert_eq!(
118 NotificationChannel::from_str("unknown"),
119 NotificationChannel::None
120 );
121 }
122
123 #[test]
124 fn test_generate_kitty_id() {
125 let id = generate_kitty_id();
126 assert!(id < 10000);
127 }
128}