Skip to main content

rskit_agent/types/
stop_reason.rs

1use rskit_ai::FinishReason;
2use serde::{Deserialize, Serialize};
3
4/// Why the agent loop terminated.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6#[non_exhaustive]
7pub enum StopReason {
8    /// The model finished its response without requesting any tool calls.
9    EndTurn,
10    /// Reached the configured maximum number of turns.
11    MaxTurns,
12    /// Exceeded the token budget.
13    MaxTokens,
14    /// Exceeded the wall-clock budget.
15    WallClockExceeded,
16    /// Exceeded the maximum tool-call budget.
17    MaxToolCallsExceeded,
18    /// The run was cancelled.
19    Cancelled,
20    /// Aborted due to a hook handler, model error, or content filter.
21    Aborted,
22}
23
24impl From<FinishReason> for StopReason {
25    fn from(reason: FinishReason) -> Self {
26        match reason {
27            FinishReason::Length => Self::MaxTokens,
28            FinishReason::Cancelled => Self::Cancelled,
29            FinishReason::Error | FinishReason::ContentFilter => Self::Aborted,
30            _ => Self::EndTurn,
31        }
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn test_stop_reason_serde() {
41        let json = serde_json::to_string(&StopReason::EndTurn).unwrap();
42        let deser: StopReason = serde_json::from_str(&json).unwrap();
43        assert!(matches!(deser, StopReason::EndTurn));
44    }
45}