Skip to main content

rs_adk/text/
route.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4
5use super::TextAgent;
6use crate::error::AgentError;
7use crate::state::State;
8
9/// A routing rule: predicate over state → target agent.
10pub struct RouteRule {
11    predicate: Box<dyn Fn(&State) -> bool + Send + Sync>,
12    agent: Arc<dyn TextAgent>,
13}
14
15impl RouteRule {
16    /// Create a new route rule with a predicate and target agent.
17    pub fn new(
18        predicate: impl Fn(&State) -> bool + Send + Sync + 'static,
19        agent: Arc<dyn TextAgent>,
20    ) -> Self {
21        Self {
22            predicate: Box::new(predicate),
23            agent,
24        }
25    }
26}
27
28/// State-driven deterministic branching — evaluates predicates in order,
29/// dispatches to the first matching agent. Falls back to default if none match.
30pub struct RouteTextAgent {
31    name: String,
32    rules: Vec<RouteRule>,
33    default: Arc<dyn TextAgent>,
34}
35
36impl RouteTextAgent {
37    /// Create a new route agent with rules and a default fallback.
38    pub fn new(
39        name: impl Into<String>,
40        rules: Vec<RouteRule>,
41        default: Arc<dyn TextAgent>,
42    ) -> Self {
43        Self {
44            name: name.into(),
45            rules,
46            default,
47        }
48    }
49}
50
51#[async_trait]
52impl TextAgent for RouteTextAgent {
53    fn name(&self) -> &str {
54        &self.name
55    }
56
57    async fn run(&self, state: &State) -> Result<String, AgentError> {
58        for rule in &self.rules {
59            if (rule.predicate)(state) {
60                return rule.agent.run(state).await;
61            }
62        }
63        self.default.run(state).await
64    }
65}