starweaver_runtime/
run.rs1use chrono::Utc;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6use starweaver_core::{ConversationId, Metadata, RunId};
7use starweaver_model::{ModelMessage, ModelResponse, ToolCallPart, ToolReturnPart};
8use starweaver_usage::Usage;
9
10#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
12#[serde(rename_all = "snake_case")]
13pub enum RunStatus {
14 Starting,
16 Running,
18 Waiting,
20 Completed,
22 Failed,
24 Cancelled,
26}
27
28#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
30pub struct AgentRunState {
31 pub run_id: RunId,
33 pub conversation_id: ConversationId,
35 pub message_history: Vec<ModelMessage>,
37 pub usage: Usage,
39 pub run_step: usize,
41 pub status: RunStatus,
43 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub output: Option<String>,
46 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub structured_output: Option<Value>,
49 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub latest_response: Option<ModelResponse>,
52 #[serde(default, skip_serializing_if = "Vec::is_empty")]
54 pub pending_tool_calls: Vec<ToolCallPart>,
55 #[serde(default, skip_serializing_if = "Vec::is_empty")]
57 pub pending_tool_returns: Vec<ToolReturnPart>,
58 #[serde(default, skip_serializing_if = "Vec::is_empty")]
60 pub pending_approval_tool_returns: Vec<ToolReturnPart>,
61 #[serde(default, skip_serializing_if = "Vec::is_empty")]
63 pub deferred_tool_returns: Vec<ToolReturnPart>,
64 #[serde(default, skip_serializing_if = "Vec::is_empty")]
66 pub idle_messages: Vec<String>,
67 #[serde(default, skip_serializing_if = "Metadata::is_empty")]
69 pub metadata: Metadata,
70}
71
72impl AgentRunState {
73 #[must_use]
75 pub fn new(run_id: RunId, conversation_id: ConversationId) -> Self {
76 Self {
77 run_id,
78 conversation_id,
79 message_history: Vec::new(),
80 usage: Usage::default(),
81 run_step: 0,
82 status: RunStatus::Starting,
83 output: None,
84 structured_output: None,
85 latest_response: None,
86 pending_tool_calls: Vec::new(),
87 pending_tool_returns: Vec::new(),
88 pending_approval_tool_returns: Vec::new(),
89 deferred_tool_returns: Vec::new(),
90 idle_messages: Vec::new(),
91 metadata: Metadata::default(),
92 }
93 }
94
95 pub fn apply_model_response(&mut self, mut response: ModelResponse) {
97 response.run_id.get_or_insert_with(|| self.run_id.clone());
98 response
99 .conversation_id
100 .get_or_insert_with(|| self.conversation_id.clone());
101 response.timestamp.get_or_insert_with(Utc::now);
102 self.usage.add_assign(&response.usage);
103 self.message_history
104 .push(ModelMessage::Response(response.clone()));
105 self.latest_response = Some(response);
106 }
107
108 pub fn replace_latest_response(&mut self, response: ModelResponse) {
110 if let Some(ModelMessage::Response(history_response)) = self.message_history.last_mut() {
111 *history_response = response.clone();
112 }
113 self.latest_response = Some(response);
114 }
115}
116
117#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
119pub struct AgentRunResult {
120 pub output: String,
122 pub state: AgentRunState,
124}