use crate::{ContentBlock, Message, Role, error::RuntimeError, runtime::RunOptions};
use super::{Agent, AgentEvent, AgentStatus, TurnRunner};
impl Agent {
pub async fn send(
&mut self,
content: impl Into<Vec<ContentBlock>>,
) -> Result<Message, RuntimeError> {
self.run(content, RunOptions::default()).await
}
pub async fn resume(&mut self) -> Result<Message, RuntimeError> {
self.resume_with_options(RunOptions::default()).await
}
pub async fn resume_with_options(
&mut self,
options: RunOptions,
) -> Result<Message, RuntimeError> {
let content = self
.memory
.resumable_user_message()
.ok_or(RuntimeError::NoResumableTurn)?
.content
.clone();
self.run(content, options).await
}
pub async fn run(
&mut self,
content: impl Into<Vec<ContentBlock>>,
options: RunOptions,
) -> Result<Message, RuntimeError> {
self.idle_requested = false;
self.refresh_tasks_from_disk()?;
let tasks_before_run = self.tasks.clone();
let rounds_before_run = self.rounds_since_task;
let task_disk_state = self.capture_task_disk_state()?;
let run_id = self.start_run_checkpoint()?;
self.memory.begin_run(
run_id,
Message {
role: Role::User,
content: content.into(),
},
)?;
self.sync_memory_snapshot();
self.emit_event(AgentEvent::RunStarted);
match TurnRunner::new(self, options).run().await {
Ok(()) => {
let final_message = self
.memory
.last_message()
.cloned()
.filter(|message| message.role == Role::Assistant);
let run_delta = self.memory.current_run_delta().unwrap_or_default();
self.clear_inflight_team_messages();
self.clear_inflight_background_notifications();
self.memory.finish_run()?;
self.sync_memory_snapshot();
self.runtime
.memory_engine()
.schedule_ingest(crate::memory::IngestRequest {
agent_id: self.id().to_string(),
source_revision: self.memory.revision(),
messages: run_delta,
});
self.set_status(AgentStatus::Finished);
self.persist_agent_record()?;
self.finish_run_checkpoint()?;
self.emit_event(AgentEvent::RunFinished);
final_message.ok_or(RuntimeError::EmptyAssistantResponse)
}
Err(error) => {
self.idle_requested = false;
self.requeue_inflight_team_messages()?;
self.requeue_inflight_background_notifications();
self.restore_task_state(tasks_before_run, rounds_before_run, &task_disk_state)?;
self.memory.rollback_failed_run()?;
self.sync_memory_snapshot();
let message = error.to_string();
self.set_status(AgentStatus::Failed(message.clone()));
self.persist_agent_record()?;
self.fail_run_checkpoint(&message)?;
self.emit_event(AgentEvent::RunFailed { error: message });
Err(error)
}
}
}
pub(crate) fn request_idle(&mut self) {
self.idle_requested = true;
}
pub(crate) fn take_idle_requested(&mut self) -> bool {
std::mem::take(&mut self.idle_requested)
}
}