Skip to main content

steer_core/app/domain/
action.rs

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}