use std::sync::Arc;
use crate::loop_::AgentEvent;
use crate::stream::StreamFn;
use crate::tool::{AgentTool, ApprovalMode};
use crate::types::{AgentMessage, ModelSpec, ThinkingLevel};
use super::{Agent, DEFAULT_PLAN_MODE_ADDENDUM};
impl Agent {
pub fn set_system_prompt(&mut self, prompt: impl Into<String>) {
self.state.system_prompt = prompt.into();
}
pub fn set_model(&mut self, model: ModelSpec) {
let old = self.state.model.clone();
if let Some((_, stream_fn)) = self.model_stream_fns.iter().find(|(m, _)| *m == model) {
self.stream_fn = Arc::clone(stream_fn);
}
self.state.model = model.clone();
if old != model {
let event = AgentEvent::ModelCycled {
old,
new: model,
reason: "set_model".to_string(),
};
self.dispatch_event(&event);
}
}
pub fn set_model_with_stream(&mut self, model: ModelSpec, stream_fn: Arc<dyn StreamFn>) {
let old = self.state.model.clone();
self.state.model = model.clone();
self.stream_fn = stream_fn;
if old != model {
let event = AgentEvent::ModelCycled {
old,
new: model,
reason: "set_model_with_stream".to_string(),
};
self.dispatch_event(&event);
}
}
pub const fn set_thinking_level(&mut self, level: ThinkingLevel) {
self.state.model.thinking_level = level;
}
pub fn set_tools(&mut self, tools: Vec<Arc<dyn AgentTool>>) {
super::assert_unique_tool_names(&tools);
self.state.tools = tools;
}
pub fn add_tool(&mut self, tool: Arc<dyn AgentTool>) {
let name = tool.name();
self.state.tools.retain(|t| t.name() != name);
self.state.tools.push(tool);
}
pub fn remove_tool(&mut self, name: &str) -> bool {
let before = self.state.tools.len();
self.state.tools.retain(|t| t.name() != name);
self.state.tools.len() < before
}
pub const fn approval_mode(&self) -> ApprovalMode {
self.approval_mode
}
pub const fn set_approval_mode(&mut self, mode: ApprovalMode) {
self.approval_mode = mode;
}
#[must_use]
pub fn find_tool(&self, name: &str) -> Option<&Arc<dyn AgentTool>> {
self.state.tools.iter().find(|t| t.name() == name)
}
#[must_use]
pub fn tools_matching(
&self,
predicate: impl Fn(&dyn AgentTool) -> bool,
) -> Vec<&Arc<dyn AgentTool>> {
self.state
.tools
.iter()
.filter(|t| predicate(t.as_ref()))
.collect()
}
#[must_use]
pub fn tools_in_namespace(&self, namespace: &str) -> Vec<&Arc<dyn AgentTool>> {
self.state
.tools
.iter()
.filter(|t| {
t.metadata()
.and_then(|m| m.namespace)
.is_some_and(|ns| ns == namespace)
})
.collect()
}
pub fn set_messages(&mut self, messages: Vec<AgentMessage>) {
self.state.messages = messages;
}
pub fn append_messages(&mut self, messages: Vec<AgentMessage>) {
self.state.messages.extend(messages);
}
pub fn clear_messages(&mut self) {
self.state.messages.clear();
}
pub fn enter_plan_mode(&mut self) -> (Vec<Arc<dyn AgentTool>>, String) {
let state = &mut self.state;
let saved_tools = state.tools.clone();
let saved_prompt = state.system_prompt.clone();
let read_only: Vec<Arc<dyn AgentTool>> = saved_tools
.iter()
.filter(|tool| !tool.requires_approval())
.cloned()
.collect();
state.tools = read_only;
let addendum = self
.plan_mode_addendum
.as_deref()
.unwrap_or(DEFAULT_PLAN_MODE_ADDENDUM);
state.system_prompt = format!("{}{addendum}", state.system_prompt);
(saved_tools, saved_prompt)
}
pub fn exit_plan_mode(&mut self, saved_tools: Vec<Arc<dyn AgentTool>>, saved_prompt: String) {
self.state.tools = saved_tools;
self.state.system_prompt = saved_prompt;
}
}