1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3
4use chrono::{DateTime, Utc};
5
6use crate::{Lifecycle, LogAvailability, LostEvidence, VersionInfo};
7
8#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
9pub struct KillByPidRequest {
10 pub pid: u32,
11 pub signal: i32,
12 pub grace_secs: u64,
13}
14
15#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
16pub struct KillByPidResponse {
17 pub pid: u32,
18 pub signal: i32,
19 pub killed_after_grace: bool,
20}
21
22#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
23pub struct StatusFilter {
24 pub session_id: Option<Uuid>,
25 #[serde(default, skip_serializing_if = "Vec::is_empty")]
26 pub session_ids: Vec<Uuid>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub updated_since: Option<DateTime<Utc>>,
29 pub runtime: Option<String>,
30 pub state: Option<String>,
31}
32
33impl StatusFilter {
34 pub const fn empty() -> Self {
35 Self {
36 session_id: None,
37 session_ids: Vec::new(),
38 updated_since: None,
39 runtime: None,
40 state: None,
41 }
42 }
43
44 pub fn requested_session_ids(&self) -> Vec<Uuid> {
45 let mut ids = self.session_ids.clone();
46 if let Some(session_id) = self.session_id
47 && !ids.contains(&session_id)
48 {
49 ids.push(session_id);
50 }
51 ids
52 }
53}
54
55impl Default for StatusFilter {
56 fn default() -> Self {
57 Self::empty()
58 }
59}
60
61#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
62pub struct StatusResponse {
63 pub lifecycles: Vec<Lifecycle>,
64}
65
66#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
67pub struct WatcherCounts {
68 pub process_exit_watchers: usize,
69 pub shim_sockets: usize,
70 pub event_waiters: usize,
71}
72
73#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
74pub struct LifecycleCounts {
75 pub forking: u64,
76 pub running: u64,
77 pub exited: u64,
78 pub lost: u64,
79}
80
81#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
82pub struct MigrationState {
83 pub applied: usize,
84 pub total: usize,
85 pub applied_descriptions: Vec<String>,
86 pub pending_descriptions: Vec<String>,
87}
88
89#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
90pub struct RecentLostEvent {
91 pub session_id: Uuid,
92 pub evidence: LostEvidence,
93 pub occurred_at: DateTime<Utc>,
94}
95
96#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
97pub struct LauncherStatus {
98 pub runtime: String,
99 pub command: Option<String>,
100 pub error: Option<String>,
101}
102
103#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
104pub struct TmuxStatus {
105 pub available: bool,
106 pub version: Option<String>,
107 pub error: Option<String>,
108}
109
110#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
111pub struct LifecycleLogAvailability {
112 pub session_id: Uuid,
113 pub log_availability: LogAvailability,
114}
115
116#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
121pub struct DoctorResponse {
122 pub version: VersionInfo,
123 pub socket_path: String,
124 pub uptime_secs: u64,
125 pub sqlite: MigrationState,
126 pub lifecycles: LifecycleCounts,
127 pub watchers: WatcherCounts,
128 pub launchers: Vec<LauncherStatus>,
129 pub tmux: TmuxStatus,
130 pub log_availability: Vec<LifecycleLogAvailability>,
131 pub last_probe_sweep: Option<DateTime<Utc>>,
132 pub recent_lost: Vec<RecentLostEvent>,
133}