1use crate::api::provider::TokenUsage;
2use crate::app::conversation::UserContent;
3use crate::app::domain::types::{CompactionId, MessageId, OpId, RequestId, SessionId, ToolCallId};
4use crate::config::model::ModelId;
5use serde::{Deserialize, Serialize};
6use steer_tools::result::ToolResult;
7use steer_tools::{ToolCall, ToolError, ToolSchema};
8
9use super::event::SessionEvent;
10
11#[derive(Debug, Clone)]
12pub enum Action {
13 UserInput {
14 session_id: SessionId,
15 content: Vec<UserContent>,
16 op_id: OpId,
17 message_id: MessageId,
18 model: ModelId,
19 timestamp: u64,
20 },
21
22 UserEditedMessage {
23 session_id: SessionId,
24 message_id: MessageId,
25 new_content: Vec<UserContent>,
26 op_id: OpId,
27 new_message_id: MessageId,
28 model: ModelId,
29 timestamp: u64,
30 },
31
32 ToolApprovalRequested {
33 session_id: SessionId,
34 request_id: RequestId,
35 tool_call: ToolCall,
36 },
37
38 ToolApprovalDecided {
39 session_id: SessionId,
40 request_id: RequestId,
41 decision: ApprovalDecision,
42 remember: Option<ApprovalMemory>,
43 },
44
45 ToolExecutionStarted {
46 session_id: SessionId,
47 tool_call_id: ToolCallId,
48 tool_name: String,
49 tool_parameters: serde_json::Value,
50 },
51
52 ToolResult {
53 session_id: SessionId,
54 tool_call_id: ToolCallId,
55 tool_name: String,
56 result: Result<ToolResult, ToolError>,
57 },
58
59 ToolSchemasAvailable {
60 session_id: SessionId,
61 tools: Vec<ToolSchema>,
62 },
63
64 ToolSchemasUpdated {
65 session_id: SessionId,
66 schemas: Vec<ToolSchema>,
67 source: SchemaSource,
68 },
69
70 SwitchPrimaryAgent {
71 session_id: SessionId,
72 agent_id: String,
73 },
74
75 McpServerStateChanged {
76 session_id: SessionId,
77 server_name: String,
78 state: McpServerState,
79 },
80
81 ModelResponseComplete {
82 session_id: SessionId,
83 op_id: OpId,
84 message_id: MessageId,
85 content: Vec<crate::app::conversation::AssistantContent>,
86 usage: Option<TokenUsage>,
87 context_window_tokens: Option<u32>,
88 configured_max_output_tokens: Option<u32>,
89 timestamp: u64,
90 },
91
92 ModelResponseError {
93 session_id: SessionId,
94 op_id: OpId,
95 error: String,
96 },
97
98 Cancel {
99 session_id: SessionId,
100 op_id: Option<OpId>,
101 },
102
103 DirectBashCommand {
104 session_id: SessionId,
105 op_id: OpId,
106 message_id: MessageId,
107 command: String,
108 timestamp: u64,
109 },
110
111 DequeueQueuedItem {
112 session_id: SessionId,
113 },
114
115 DrainQueuedWork {
116 session_id: SessionId,
117 },
118
119 RequestCompaction {
120 session_id: SessionId,
121 op_id: OpId,
122 model: ModelId,
123 },
124
125 Shutdown,
126
127 Hydrate {
128 session_id: SessionId,
129 events: Vec<SessionEvent>,
130 starting_sequence: u64,
131 },
132
133 WorkspaceFilesListed {
134 session_id: SessionId,
135 files: Vec<String>,
136 },
137
138 CompactionComplete {
139 session_id: SessionId,
140 op_id: OpId,
141 compaction_id: CompactionId,
142 summary_message_id: MessageId,
143 summary: String,
144 compacted_head_message_id: MessageId,
145 previous_active_message_id: Option<MessageId>,
146 model: String,
147 timestamp: u64,
148 },
149
150 CompactionFailed {
151 session_id: SessionId,
152 op_id: OpId,
153 error: String,
154 },
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
158pub enum ApprovalDecision {
159 Approved,
160 Denied,
161}
162
163#[derive(Debug, Clone, Serialize, Deserialize)]
164pub enum ApprovalMemory {
165 Tool(String),
166 BashPattern(String),
167 PendingTool,
168}
169
170#[derive(Debug, Clone, Serialize, Deserialize)]
171pub enum SchemaSource {
172 Workspace,
173 Mcp { server_name: String },
174 Backend { backend_name: String },
175}
176
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub enum McpServerState {
179 Connecting,
180 Connected { tools: Vec<ToolSchema> },
181 Disconnected { error: Option<String> },
182 Failed { error: String },
183}
184
185impl Action {
186 pub fn session_id(&self) -> Option<SessionId> {
187 match self {
188 Action::UserInput { session_id, .. }
189 | Action::UserEditedMessage { session_id, .. }
190 | Action::ToolApprovalRequested { session_id, .. }
191 | Action::ToolApprovalDecided { session_id, .. }
192 | Action::ToolExecutionStarted { session_id, .. }
193 | Action::ToolResult { session_id, .. }
194 | Action::ToolSchemasAvailable { session_id, .. }
195 | Action::ToolSchemasUpdated { session_id, .. }
196 | Action::SwitchPrimaryAgent { session_id, .. }
197 | Action::McpServerStateChanged { session_id, .. }
198 | Action::ModelResponseComplete { session_id, .. }
199 | Action::ModelResponseError { session_id, .. }
200 | Action::Cancel { session_id, .. }
201 | Action::DirectBashCommand { session_id, .. }
202 | Action::DequeueQueuedItem { session_id, .. }
203 | Action::DrainQueuedWork { session_id, .. }
204 | Action::RequestCompaction { session_id, .. }
205 | Action::Hydrate { session_id, .. }
206 | Action::WorkspaceFilesListed { session_id, .. }
207 | Action::CompactionComplete { session_id, .. }
208 | Action::CompactionFailed { session_id, .. } => Some(*session_id),
209 Action::Shutdown => None,
210 }
211 }
212
213 pub fn op_id(&self) -> Option<OpId> {
214 match self {
215 Action::UserInput { op_id, .. }
216 | Action::UserEditedMessage { op_id, .. }
217 | Action::DirectBashCommand { op_id, .. }
218 | Action::RequestCompaction { op_id, .. }
219 | Action::ModelResponseComplete { op_id, .. }
220 | Action::ModelResponseError { op_id, .. }
221 | Action::CompactionComplete { op_id, .. }
222 | Action::CompactionFailed { op_id, .. } => Some(*op_id),
223 Action::Cancel { op_id, .. } => *op_id,
224 _ => None,
225 }
226 }
227}