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 timestamp: u64,
89 },
90
91 ModelResponseError {
92 session_id: SessionId,
93 op_id: OpId,
94 error: String,
95 },
96
97 Cancel {
98 session_id: SessionId,
99 op_id: Option<OpId>,
100 },
101
102 DirectBashCommand {
103 session_id: SessionId,
104 op_id: OpId,
105 message_id: MessageId,
106 command: String,
107 timestamp: u64,
108 },
109
110 DequeueQueuedItem {
111 session_id: SessionId,
112 },
113
114 DrainQueuedWork {
115 session_id: SessionId,
116 },
117
118 RequestCompaction {
119 session_id: SessionId,
120 op_id: OpId,
121 model: ModelId,
122 },
123
124 Shutdown,
125
126 Hydrate {
127 session_id: SessionId,
128 events: Vec<SessionEvent>,
129 starting_sequence: u64,
130 },
131
132 WorkspaceFilesListed {
133 session_id: SessionId,
134 files: Vec<String>,
135 },
136
137 CompactionComplete {
138 session_id: SessionId,
139 op_id: OpId,
140 compaction_id: CompactionId,
141 summary_message_id: MessageId,
142 summary: String,
143 compacted_head_message_id: MessageId,
144 previous_active_message_id: Option<MessageId>,
145 model: String,
146 timestamp: u64,
147 },
148
149 CompactionFailed {
150 session_id: SessionId,
151 op_id: OpId,
152 error: String,
153 },
154}
155
156#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
157pub enum ApprovalDecision {
158 Approved,
159 Denied,
160}
161
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub enum ApprovalMemory {
164 Tool(String),
165 BashPattern(String),
166 PendingTool,
167}
168
169#[derive(Debug, Clone, Serialize, Deserialize)]
170pub enum SchemaSource {
171 Workspace,
172 Mcp { server_name: String },
173 Backend { backend_name: String },
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
177pub enum McpServerState {
178 Connecting,
179 Connected { tools: Vec<ToolSchema> },
180 Disconnected { error: Option<String> },
181 Failed { error: String },
182}
183
184impl Action {
185 pub fn session_id(&self) -> Option<SessionId> {
186 match self {
187 Action::UserInput { session_id, .. }
188 | Action::UserEditedMessage { session_id, .. }
189 | Action::ToolApprovalRequested { session_id, .. }
190 | Action::ToolApprovalDecided { session_id, .. }
191 | Action::ToolExecutionStarted { session_id, .. }
192 | Action::ToolResult { session_id, .. }
193 | Action::ToolSchemasAvailable { session_id, .. }
194 | Action::ToolSchemasUpdated { session_id, .. }
195 | Action::SwitchPrimaryAgent { session_id, .. }
196 | Action::McpServerStateChanged { session_id, .. }
197 | Action::ModelResponseComplete { session_id, .. }
198 | Action::ModelResponseError { session_id, .. }
199 | Action::Cancel { session_id, .. }
200 | Action::DirectBashCommand { session_id, .. }
201 | Action::DequeueQueuedItem { session_id, .. }
202 | Action::DrainQueuedWork { session_id, .. }
203 | Action::RequestCompaction { session_id, .. }
204 | Action::Hydrate { session_id, .. }
205 | Action::WorkspaceFilesListed { session_id, .. }
206 | Action::CompactionComplete { session_id, .. }
207 | Action::CompactionFailed { session_id, .. } => Some(*session_id),
208 Action::Shutdown => None,
209 }
210 }
211
212 pub fn op_id(&self) -> Option<OpId> {
213 match self {
214 Action::UserInput { op_id, .. }
215 | Action::UserEditedMessage { op_id, .. }
216 | Action::DirectBashCommand { op_id, .. }
217 | Action::RequestCompaction { op_id, .. }
218 | Action::ModelResponseComplete { op_id, .. }
219 | Action::ModelResponseError { op_id, .. }
220 | Action::CompactionComplete { op_id, .. }
221 | Action::CompactionFailed { op_id, .. } => Some(*op_id),
222 Action::Cancel { op_id, .. } => *op_id,
223 _ => None,
224 }
225 }
226}