Skip to main content

vtcode_core/open_responses/
status.rs

1//! Unified item status for Open Responses state machines.
2//!
3//! All items in Open Responses follow a state machine model with defined
4//! lifecycle states. This module provides the canonical status enum used
5//! across all item types.
6
7use serde::{Deserialize, Serialize};
8
9/// Lifecycle status for items in the Open Responses model.
10///
11/// Per the Open Responses specification, all items are state machines that
12/// transition through these defined states during their lifecycle.
13///
14/// # State Transitions
15///
16/// ```text
17/// ┌─────────────┐
18/// │ in_progress │──────────────────────────────────┐
19/// └──────┬──────┘                                  │
20///        │                                         │
21///        ▼                                         ▼
22/// ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
23/// │ incomplete  │     │  completed  │     │   failed    │
24/// └─────────────┘     └─────────────┘     └─────────────┘
25///   (terminal)          (terminal)          (terminal)
26/// ```
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
28#[serde(rename_all = "snake_case")]
29pub enum ItemStatus {
30    /// The model is currently emitting tokens belonging to this item.
31    #[default]
32    InProgress,
33
34    /// The model has exhausted its token budget while emitting tokens for this item.
35    /// This is a terminal state. If an item ends in this state, it MUST be the last
36    /// item emitted, and the containing response MUST also be in an `incomplete` state.
37    Incomplete,
38
39    /// The model has finished emitting tokens for this item, and/or a tool call
40    /// has completed successfully. This is a terminal state.
41    Completed,
42
43    /// The item processing has failed. This is a terminal state.
44    Failed,
45}
46
47impl ItemStatus {
48    /// Returns `true` if this status is a terminal state (no further transitions allowed).
49    #[inline]
50    pub fn is_terminal(&self) -> bool {
51        matches!(self, Self::Incomplete | Self::Completed | Self::Failed)
52    }
53
54    /// Returns `true` if this status indicates successful completion.
55    #[inline]
56    pub fn is_success(&self) -> bool {
57        matches!(self, Self::Completed)
58    }
59
60    /// Returns `true` if this status indicates a failure.
61    #[inline]
62    pub fn is_failure(&self) -> bool {
63        matches!(self, Self::Failed | Self::Incomplete)
64    }
65}
66
67impl std::fmt::Display for ItemStatus {
68    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
69        match self {
70            Self::InProgress => write!(f, "in_progress"),
71            Self::Incomplete => write!(f, "incomplete"),
72            Self::Completed => write!(f, "completed"),
73            Self::Failed => write!(f, "failed"),
74        }
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_terminal_states() {
84        assert!(!ItemStatus::InProgress.is_terminal());
85        assert!(ItemStatus::Incomplete.is_terminal());
86        assert!(ItemStatus::Completed.is_terminal());
87        assert!(ItemStatus::Failed.is_terminal());
88    }
89
90    #[test]
91    fn test_success_failure() {
92        assert!(!ItemStatus::InProgress.is_success());
93        assert!(ItemStatus::Completed.is_success());
94        assert!(!ItemStatus::Failed.is_success());
95
96        assert!(!ItemStatus::InProgress.is_failure());
97        assert!(!ItemStatus::Completed.is_failure());
98        assert!(ItemStatus::Failed.is_failure());
99        assert!(ItemStatus::Incomplete.is_failure());
100    }
101
102    #[test]
103    fn test_serialization() {
104        assert_eq!(
105            serde_json::to_string(&ItemStatus::InProgress).unwrap(),
106            "\"in_progress\""
107        );
108        assert_eq!(
109            serde_json::to_string(&ItemStatus::Completed).unwrap(),
110            "\"completed\""
111        );
112    }
113}