mod action;
mod context;
mod deciders;
mod state;
pub use action::{Action, ActionKind, ActionResult};
pub use context::DecisionContext;
pub use deciders::{
ComposableDecider,
Decider,
DecisionModifier,
ErrorAwareModifier,
MurmurationDecider,
ParameterizedDecider,
PlainDecider,
RetryModifier,
StallDetectionModifier,
SuccessRateModifier,
};
pub use state::{AgentState, ErrorInfo, FileState};
use std::sync::Arc;
#[derive(Debug, Clone, Default)]
pub enum AgentMode {
#[default]
Plain,
Agentic(Arc<dyn Decider>),
}
impl AgentMode {
pub fn plain() -> Self {
Self::Plain
}
pub fn agentic(decider: impl Decider + 'static) -> Self {
Self::Agentic(Arc::new(decider))
}
pub fn is_plain(&self) -> bool {
matches!(self, Self::Plain)
}
pub fn is_agentic(&self) -> bool {
matches!(self, Self::Agentic(_))
}
pub fn decider(&self) -> Option<&dyn Decider> {
match self {
Self::Agentic(d) => Some(d.as_ref()),
Self::Plain => None,
}
}
}
#[derive(Debug, Clone)]
pub struct DeciderConfig {
pub mode: AgentMode,
pub max_retries: u32,
pub enable_escalation: bool,
pub escalation_threshold: f64,
}
impl Default for DeciderConfig {
fn default() -> Self {
Self {
mode: AgentMode::Plain,
max_retries: 3,
enable_escalation: true,
escalation_threshold: 0.4,
}
}
}
impl DeciderConfig {
pub fn plain() -> Self {
Self::default()
}
pub fn parameterized() -> Self {
Self {
mode: AgentMode::agentic(ParameterizedDecider::default()),
..Default::default()
}
}
pub fn murmuration() -> Self {
Self {
mode: AgentMode::agentic(MurmurationDecider::default()),
..Default::default()
}
}
pub fn with_decider(decider: impl Decider + 'static) -> Self {
Self {
mode: AgentMode::agentic(decider),
..Default::default()
}
}
pub fn max_retries(mut self, n: u32) -> Self {
self.max_retries = n;
self
}
pub fn escalation(mut self, enable: bool) -> Self {
self.enable_escalation = enable;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_agent_mode_plain() {
let mode = AgentMode::plain();
assert!(mode.is_plain());
assert!(!mode.is_agentic());
assert!(mode.decider().is_none());
}
#[test]
fn test_agent_mode_agentic() {
let mode = AgentMode::agentic(ParameterizedDecider::default());
assert!(!mode.is_plain());
assert!(mode.is_agentic());
assert!(mode.decider().is_some());
assert_eq!(mode.decider().unwrap().name(), "ParameterizedDecider");
}
#[test]
fn test_decider_config() {
let config = DeciderConfig::parameterized();
assert!(config.mode.is_agentic());
assert_eq!(config.max_retries, 3);
let config = DeciderConfig::plain().max_retries(5).escalation(false);
assert!(config.mode.is_plain());
assert_eq!(config.max_retries, 5);
assert!(!config.enable_escalation);
}
}