traitclaw_test_utils/
runtime.rs1use std::sync::Arc;
17
18use async_trait::async_trait;
19
20use traitclaw_core::config::AgentConfig;
21use traitclaw_core::traits::context_manager::ContextManager;
22use traitclaw_core::traits::output_transformer::OutputTransformer;
23use traitclaw_core::traits::provider::Provider;
24use traitclaw_core::traits::strategy::AgentRuntime;
25use traitclaw_core::traits::tool::ErasedTool;
26use traitclaw_core::traits::tool_registry::SimpleRegistry;
27use traitclaw_core::traits::tracker::Tracker;
28use traitclaw_core::types::agent_state::AgentState;
29use traitclaw_core::types::completion::CompletionResponse;
30use traitclaw_core::types::message::Message;
31
32use crate::memory::MockMemory;
33
34pub(crate) struct NoopTracker;
37
38impl Tracker for NoopTracker {
39 fn on_iteration(&self, _state: &mut AgentState) {}
40 fn on_tool_call(&self, _name: &str, _args: &serde_json::Value, _state: &mut AgentState) {}
41 fn on_llm_response(&self, _response: &CompletionResponse, _state: &mut AgentState) {}
42 fn recommended_concurrency(&self, _state: &AgentState) -> usize {
43 usize::MAX
44 }
45}
46
47pub(crate) struct NoopContextManager;
48
49#[async_trait]
50impl ContextManager for NoopContextManager {
51 async fn prepare(
52 &self,
53 _messages: &mut Vec<Message>,
54 _context_window: usize,
55 _state: &mut AgentState,
56 ) {
57 }
58}
59
60pub(crate) struct NoopOutputTransformer;
61
62#[async_trait]
63impl OutputTransformer for NoopOutputTransformer {
64 async fn transform(&self, output: String, _tool_name: &str, _state: &AgentState) -> String {
65 output
66 }
67}
68
69pub fn make_runtime(
92 provider: impl Provider + 'static,
93 tools: Vec<Arc<dyn ErasedTool>>,
94) -> AgentRuntime {
95 make_runtime_with_config(provider, tools, AgentConfig::default())
96}
97
98pub fn make_runtime_with_config(
117 provider: impl Provider + 'static,
118 tools: Vec<Arc<dyn ErasedTool>>,
119 config: AgentConfig,
120) -> AgentRuntime {
121 AgentRuntime {
122 provider: Arc::new(provider),
123 tools: tools.clone(),
124 memory: Arc::new(MockMemory::new()),
125 guards: vec![],
126 hints: vec![],
127 tracker: Arc::new(NoopTracker),
128 context_manager: Arc::new(NoopContextManager),
129 execution_strategy: Arc::new(traitclaw_core::SequentialStrategy),
130 output_transformer: Arc::new(NoopOutputTransformer),
131 tool_registry: Arc::new(SimpleRegistry::new(tools)),
132 config,
133 hooks: vec![],
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use crate::provider::MockProvider;
141
142 #[test]
143 fn test_make_runtime_returns_valid_runtime() {
144 let rt = make_runtime(MockProvider::text("ok"), vec![]);
145 assert!(rt.guards.is_empty());
146 assert!(rt.hints.is_empty());
147 assert!(rt.hooks.is_empty());
148 assert!(rt.tools.is_empty());
149 }
150
151 #[test]
152 fn test_make_runtime_uses_default_config() {
153 let rt = make_runtime(MockProvider::text("ok"), vec![]);
154 assert_eq!(rt.config.max_iterations, 20);
155 }
156
157 #[test]
158 fn test_make_runtime_with_config_applies_custom_config() {
159 let mut config = AgentConfig::default();
160 config.max_iterations = 3;
161 let rt = make_runtime_with_config(MockProvider::text("ok"), vec![], config);
162 assert_eq!(rt.config.max_iterations, 3);
163 }
164
165 #[test]
166 fn test_make_runtime_with_tools() {
167 use crate::tools::EchoTool;
168
169 let echo: Arc<dyn ErasedTool> = Arc::new(EchoTool);
170 let rt = make_runtime(MockProvider::text("ok"), vec![echo]);
171 assert_eq!(rt.tools.len(), 1);
172 }
173}