mod types;
pub use types::*;
use crate::error::Result;
use crate::harness::cancel::CancellationToken;
use crate::harness::events::{AgentEvent, EventRecord, EventSink};
use crate::harness::ids::{RunId, ThreadId};
use crate::harness::limits::{LimitTracker, RunLimits};
use crate::harness::store::StoreRegistry;
impl RunConfig {
pub fn new(run_id: impl Into<String>) -> Self {
Self {
run_id: RunId::new(run_id),
thread_id: None,
tags: Vec::new(),
metadata: serde_json::Value::Null,
timeout_ms: None,
max_model_calls: 25,
max_tool_calls: 50,
max_turn_output_tokens: None,
depth: 0,
max_depth: RunLimits::default().max_depth,
}
}
pub fn with_thread(mut self, thread_id: impl Into<String>) -> Self {
self.thread_id = Some(ThreadId::new(thread_id));
self
}
pub fn with_tag(mut self, tag: impl Into<String>) -> Self {
self.tags.push(tag.into());
self
}
pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
self.metadata = metadata;
self
}
pub fn with_timeout_ms(mut self, timeout_ms: u64) -> Self {
self.timeout_ms = Some(timeout_ms);
self
}
pub fn with_max_model_calls(mut self, n: usize) -> Self {
self.max_model_calls = n;
self
}
pub fn with_max_tool_calls(mut self, n: usize) -> Self {
self.max_tool_calls = n;
self
}
pub fn with_max_turn_output_tokens(mut self, n: u32) -> Self {
self.max_turn_output_tokens = Some(n);
self
}
pub fn with_depth(mut self, depth: usize) -> Self {
self.depth = depth;
self
}
pub fn with_max_depth(mut self, max_depth: usize) -> Self {
self.max_depth = max_depth;
self
}
pub fn child(&self, child_run_id: impl Into<String>) -> Self {
let mut config = Self::new(child_run_id);
config.depth = self.depth + 1;
config.max_depth = self.max_depth;
config.thread_id = self.thread_id.clone();
config.max_turn_output_tokens = self.max_turn_output_tokens;
config
}
fn to_run_limits(&self) -> RunLimits {
RunLimits::default()
.with_max_model_calls(self.max_model_calls)
.with_max_tool_calls(self.max_tool_calls)
.with_max_wall_clock_ms(self.timeout_ms)
.with_max_depth(self.max_depth)
}
}
impl<Ctx> RunContext<Ctx> {
pub fn new(config: RunConfig, data: Ctx) -> Self {
let limits = LimitTracker::new(config.to_run_limits());
Self {
config,
data,
stores: StoreRegistry::new(),
events: EventSink::new(),
limits,
steering: None,
cancellation: CancellationToken::new(),
}
}
pub fn with_cancellation(mut self, cancellation: CancellationToken) -> Self {
self.cancellation = cancellation;
self
}
pub fn with_stores(mut self, stores: StoreRegistry) -> Self {
self.stores = stores;
self
}
pub fn with_events(mut self, events: EventSink) -> Self {
self.events = events;
self
}
pub fn with_steering(mut self, steering: crate::harness::steering::SteeringHandle) -> Self {
self.steering = Some(steering);
self
}
pub fn emit(&self, event: AgentEvent) -> EventRecord {
self.events.emit(event)
}
pub fn run_id(&self) -> &RunId {
&self.config.run_id
}
pub fn thread_id(&self) -> Option<&ThreadId> {
self.config.thread_id.as_ref()
}
pub fn depth(&self) -> usize {
self.config.depth
}
pub fn max_depth(&self) -> usize {
self.config.max_depth
}
pub fn record_model_call(&mut self) -> Result<()> {
self.limits.record_model_call()
}
pub fn record_tool_call(&mut self) -> Result<()> {
self.limits.record_tool_call()
}
pub fn check_deadline(&mut self) -> Result<()> {
self.limits.check_wall_clock()
}
pub fn remaining_wall_clock(&self) -> Option<std::time::Duration> {
self.limits.remaining_wall_clock()
}
}
#[cfg(test)]
mod test;