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 Box::pin(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 = Box::pin(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 = Box::pin(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 =
66 Box::pin(self.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 Box::pin(self.run_with_history_and_stream_events(prompt, Vec::new(), events)).await
87 }
88
89 pub async fn run_with_history_and_stream_events(
95 &self,
96 prompt: impl Into<AgentInput>,
97 message_history: Vec<ModelMessage>,
98 events: &mut Vec<AgentStreamRecord>,
99 ) -> Result<AgentResult, AgentError> {
100 let mut context = self.context_from_history(message_history);
101 Box::pin(self.run_with_context_and_stream_events(prompt, &mut context, events)).await
102 }
103
104 pub async fn run_with_history(
110 &self,
111 prompt: impl Into<AgentInput>,
112 message_history: Vec<ModelMessage>,
113 ) -> Result<AgentResult, AgentError> {
114 let mut context = self.context_from_history(message_history);
115 Box::pin(self.run_with_context(prompt, &mut context)).await
116 }
117
118 pub async fn run_with_context_iter(
124 &self,
125 prompt: impl Into<AgentInput>,
126 context: &mut AgentContext,
127 ) -> Result<AgentIterResult, AgentError> {
128 let mut events = Vec::new();
129 let result =
130 Box::pin(self.run_with_context_and_stream_events(prompt, context, &mut events)).await?;
131 let iterations = AgentIterationTrace::from_stream_records(&events);
132 Ok(AgentIterResult {
133 result,
134 iterations,
135 events,
136 })
137 }
138
139 pub async fn run_with_context_and_stream_events(
145 &self,
146 prompt: impl Into<AgentInput>,
147 context: &mut AgentContext,
148 events: &mut Vec<AgentStreamRecord>,
149 ) -> Result<AgentResult, AgentError> {
150 Box::pin(self.run_with_context_inner(prompt, context, Some(events))).await
151 }
152
153 #[allow(clippy::too_many_lines)]
159 pub async fn run_with_context(
160 &self,
161 prompt: impl Into<AgentInput>,
162 context: &mut AgentContext,
163 ) -> Result<AgentResult, AgentError> {
164 Box::pin(self.run_with_context_inner(prompt, context, None)).await
165 }
166 fn context_from_history(&self, message_history: Vec<ModelMessage>) -> AgentContext {
167 let conversation_id = latest_conversation_id(&message_history).unwrap_or_default();
168 let mut context = self.new_context();
169 context.conversation_id = conversation_id;
170 context.message_history = message_history;
171 context
172 }
173}
174
175fn latest_conversation_id(message_history: &[ModelMessage]) -> Option<ConversationId> {
176 message_history
177 .iter()
178 .rev()
179 .find_map(|message| match message {
180 ModelMessage::Request(request) => request.conversation_id.clone(),
181 ModelMessage::Response(response) => response.conversation_id.clone(),
182 })
183}