Skip to main content

agent_graph_mcp/
lifecycle.rs

1//! Canonical execution lifecycle classification.
2#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum Lifecycle {
4    Accepted,
5    Running,
6    Completed,
7    Failed,
8    Cancelled,
9    Interrupted,
10}
11impl Lifecycle {
12    pub fn classify(status: &str) -> Self {
13        match status {
14            "accepted" => Self::Accepted,
15            "running" => Self::Running,
16            "completed" => Self::Completed,
17            "failed" => Self::Failed,
18            "cancelled" => Self::Cancelled,
19            "interrupted" | "interrupted_non_resumable" | "interrupted_resumable" => {
20                Self::Interrupted
21            }
22            _ => Self::Failed,
23        }
24    }
25    pub fn is_terminal(self) -> bool {
26        matches!(
27            self,
28            Self::Completed | Self::Failed | Self::Cancelled | Self::Interrupted
29        )
30    }
31}
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct TimeoutDisposition {
34    pub completion_unknown: bool,
35    pub cancellation_requested: bool,
36}
37pub fn synchronous_timeout() -> TimeoutDisposition {
38    TimeoutDisposition {
39        completion_unknown: true,
40        cancellation_requested: true,
41    }
42}
43#[cfg(test)]
44mod tests {
45    use super::*;
46    #[test]
47    fn all_states_are_canonical() {
48        assert_eq!(Lifecycle::classify("running"), Lifecycle::Running);
49        assert!(Lifecycle::classify("interrupted_non_resumable").is_terminal());
50        assert_eq!(
51            synchronous_timeout(),
52            TimeoutDisposition {
53                completion_unknown: true,
54                cancellation_requested: true
55            }
56        );
57    }
58}