starweaver_runtime/agent/run_loop/
entrypoints.rs1use starweaver_context::AgentContext;
2use starweaver_core::ConversationId;
3use starweaver_model::ModelMessage;
4
5use crate::{
6 agent::{Agent, AgentError, AgentInput, AgentResult},
7 iteration::{AgentIterResult, AgentIterationTrace},
8 stream::{AgentStreamRecord, AgentStreamResult},
9};
10
11impl Agent {
12 pub async fn run(&self, prompt: impl Into<AgentInput>) -> Result<AgentResult, AgentError> {
18 self.run_with_history(prompt, Vec::new()).await
19 }
20
21 pub async fn run_iter(
27 &self,
28 prompt: impl Into<AgentInput>,
29 ) -> Result<AgentIterResult, AgentError> {
30 let mut events = Vec::new();
31 let result = self.run_with_stream_events(prompt, &mut events).await?;
32 let iterations = AgentIterationTrace::from_stream_records(&events);
33 Ok(AgentIterResult {
34 result,
35 iterations,
36 events,
37 })
38 }
39
40 pub async fn run_stream(
46 &self,
47 prompt: impl Into<AgentInput>,
48 ) -> Result<AgentStreamResult, AgentError> {
49 let mut events = Vec::new();
50 let result = self.run_with_stream_events(prompt, &mut events).await?;
51 Ok(AgentStreamResult { result, events })
52 }
53
54 pub async fn run_with_history_iter(
60 &self,
61 prompt: impl Into<AgentInput>,
62 message_history: Vec<ModelMessage>,
63 ) -> Result<AgentIterResult, AgentError> {
64 let mut events = Vec::new();
65 let result = self
66 .run_with_history_and_stream_events(prompt, message_history, &mut events)
67 .await?;
68 let iterations = AgentIterationTrace::from_stream_records(&events);
69 Ok(AgentIterResult {
70 result,
71 iterations,
72 events,
73 })
74 }
75
76 pub async fn run_with_stream_events(
82 &self,
83 prompt: impl Into<AgentInput>,
84 events: &mut Vec<AgentStreamRecord>,
85 ) -> Result<AgentResult, AgentError> {
86 self.run_with_history_and_stream_events(prompt, Vec::new(), events)
87 .await
88 }
89
90 pub async fn run_with_history_and_stream_events(
96 &self,
97 prompt: impl Into<AgentInput>,
98 message_history: Vec<ModelMessage>,
99 events: &mut Vec<AgentStreamRecord>,
100 ) -> Result<AgentResult, AgentError> {
101 let mut context = self.context_from_history(message_history);
102 self.run_with_context_and_stream_events(prompt, &mut context, events)
103 .await
104 }
105
106 pub async fn run_with_history(
112 &self,
113 prompt: impl Into<AgentInput>,
114 message_history: Vec<ModelMessage>,
115 ) -> Result<AgentResult, AgentError> {
116 let mut context = self.context_from_history(message_history);
117 self.run_with_context(prompt, &mut context).await
118 }
119
120 pub async fn run_with_context_iter(
126 &self,
127 prompt: impl Into<AgentInput>,
128 context: &mut AgentContext,
129 ) -> Result<AgentIterResult, AgentError> {
130 let mut events = Vec::new();
131 let result = self
132 .run_with_context_and_stream_events(prompt, context, &mut events)
133 .await?;
134 let iterations = AgentIterationTrace::from_stream_records(&events);
135 Ok(AgentIterResult {
136 result,
137 iterations,
138 events,
139 })
140 }
141
142 pub async fn run_with_context_and_stream_events(
148 &self,
149 prompt: impl Into<AgentInput>,
150 context: &mut AgentContext,
151 events: &mut Vec<AgentStreamRecord>,
152 ) -> Result<AgentResult, AgentError> {
153 self.run_with_context_inner(prompt, context, Some(events))
154 .await
155 }
156
157 #[allow(clippy::too_many_lines)]
163 pub async fn run_with_context(
164 &self,
165 prompt: impl Into<AgentInput>,
166 context: &mut AgentContext,
167 ) -> Result<AgentResult, AgentError> {
168 self.run_with_context_inner(prompt, context, None).await
169 }
170 fn context_from_history(&self, message_history: Vec<ModelMessage>) -> AgentContext {
171 let conversation_id = latest_conversation_id(&message_history).unwrap_or_default();
172 let mut context = self.new_context();
173 context.conversation_id = conversation_id;
174 context.message_history = message_history;
175 context
176 }
177}
178
179fn latest_conversation_id(message_history: &[ModelMessage]) -> Option<ConversationId> {
180 message_history
181 .iter()
182 .rev()
183 .find_map(|message| match message {
184 ModelMessage::Request(request) => request.conversation_id.clone(),
185 ModelMessage::Response(response) => response.conversation_id.clone(),
186 })
187}