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