1use std::borrow::Cow;
4
5use swiftide_core::chat_completion::ToolCall;
6
7#[derive(Clone, Debug, Default, strum_macros::EnumDiscriminants, strum_macros::EnumIs)]
8pub enum State {
9 #[default]
10 Pending,
11 Running,
12 Stopped(StopReason),
13}
14
15impl State {
16 pub fn stop_reason(&self) -> Option<&StopReason> {
17 match self {
18 State::Stopped(reason) => Some(reason),
19 _ => None,
20 }
21 }
22}
23
24#[non_exhaustive]
28#[derive(Clone, Debug, strum_macros::EnumIs, PartialEq)]
29pub enum StopReason {
30 RequestedByTool(ToolCall, Option<Cow<'static, str>>),
32
33 AgentFailed(Option<Cow<'static, str>>),
35
36 ToolCallsOverLimit(ToolCall),
38
39 FeedbackRequired {
41 tool_call: ToolCall,
42 payload: Option<serde_json::Value>,
43 },
44 Error,
46
47 NoNewMessages,
49
50 Other(String),
51}
52
53impl StopReason {
54 pub fn as_requested_by_tool(&self) -> Option<(&ToolCall, Option<&str>)> {
55 if let StopReason::RequestedByTool(t, message) = self {
56 Some((t, message.as_deref()))
57 } else {
58 None
59 }
60 }
61
62 pub fn as_tool_calls_over_limit(&self) -> Option<&ToolCall> {
63 if let StopReason::ToolCallsOverLimit(t) = self {
64 Some(t)
65 } else {
66 None
67 }
68 }
69
70 pub fn as_feedback_required(&self) -> Option<(&ToolCall, Option<&serde_json::Value>)> {
71 if let StopReason::FeedbackRequired { tool_call, payload } = self {
72 Some((tool_call, payload.as_ref()))
73 } else {
74 None
75 }
76 }
77
78 pub fn as_error(&self) -> Option<()> {
79 if matches!(self, StopReason::Error) {
80 Some(())
81 } else {
82 None
83 }
84 }
85
86 pub fn as_no_new_messages(&self) -> Option<()> {
87 if matches!(self, StopReason::NoNewMessages) {
88 Some(())
89 } else {
90 None
91 }
92 }
93
94 pub fn as_other(&self) -> Option<&str> {
95 if let StopReason::Other(s) = self {
96 Some(s)
97 } else {
98 None
99 }
100 }
101}
102impl Default for StopReason {
103 fn default() -> Self {
104 StopReason::Other("No reason provided".into())
105 }
106}
107
108impl<S: AsRef<str>> From<S> for StopReason {
109 fn from(value: S) -> Self {
110 StopReason::Other(value.as_ref().to_string())
111 }
112}