Skip to main content

sim_lib_openai_server/plan/
combinators.rs

1use sim_kernel::{Expr, Symbol};
2
3/// Static description of a plan combinator: its name and structural constraints.
4#[derive(Clone, Debug, PartialEq, Eq)]
5pub struct PlanCombinator {
6    /// Combinator name without the `plan/` prefix (for example `race`).
7    pub name: &'static str,
8    /// Minimum number of child plans the combinator accepts.
9    pub min_children: usize,
10    /// Maximum number of child plans the combinator accepts.
11    pub max_children: usize,
12    /// Keyword argument names the combinator recognizes.
13    pub keywords: &'static [&'static str],
14    /// Whether the combinator can be executed by the current evaluator.
15    pub executable_now: bool,
16}
17
18/// Returns the full table of known plan combinators.
19pub fn plan_combinators() -> &'static [PlanCombinator] {
20    &PLAN_COMBINATORS
21}
22
23/// Returns the combinator table encoded as a list of map [`Expr`] records.
24pub fn plan_combinators_expr() -> Expr {
25    Expr::List(PLAN_COMBINATORS.iter().map(plan_combinator_expr).collect())
26}
27
28/// Returns the `plan/<name>` head symbol for a combinator name.
29pub fn plan_symbol(name: &str) -> Symbol {
30    Symbol::new(format!("plan/{name}"))
31}
32
33/// Looks up a combinator by its name, returning `None` if it is not known.
34pub fn combinator_by_name(name: &str) -> Option<&'static PlanCombinator> {
35    PLAN_COMBINATORS
36        .iter()
37        .find(|combinator| combinator.name == name)
38}
39
40fn plan_combinator_expr(combinator: &PlanCombinator) -> Expr {
41    Expr::Map(vec![
42        field("name", Expr::Symbol(plan_symbol(combinator.name))),
43        field(
44            "min-children",
45            Expr::String(combinator.min_children.to_string()),
46        ),
47        field(
48            "max-children",
49            Expr::String(combinator.max_children.to_string()),
50        ),
51        field(
52            "keywords",
53            Expr::List(
54                combinator
55                    .keywords
56                    .iter()
57                    .map(|keyword| Expr::Symbol(Symbol::new(*keyword)))
58                    .collect(),
59            ),
60        ),
61        field("executable-now", Expr::Bool(combinator.executable_now)),
62    ])
63}
64
65use sim_value::build::entry as field;
66
67const PLAN_COMBINATORS: [PlanCombinator; 12] = [
68    PlanCombinator {
69        name: "atom",
70        min_children: 1,
71        max_children: 1,
72        keywords: &[],
73        executable_now: true,
74    },
75    PlanCombinator {
76        name: "race",
77        min_children: 1,
78        max_children: 4,
79        keywords: &["deadline"],
80        executable_now: true,
81    },
82    PlanCombinator {
83        name: "market",
84        min_children: 1,
85        max_children: 1,
86        keywords: &[],
87        executable_now: true,
88    },
89    PlanCombinator {
90        name: "verify",
91        min_children: 2,
92        max_children: 2,
93        keywords: &["on-fail"],
94        executable_now: true,
95    },
96    PlanCombinator {
97        name: "debate",
98        min_children: 2,
99        max_children: 4,
100        keywords: &["judge", "rounds"],
101        executable_now: true,
102    },
103    PlanCombinator {
104        name: "chain",
105        min_children: 1,
106        max_children: 4,
107        keywords: &[],
108        executable_now: true,
109    },
110    PlanCombinator {
111        name: "fallback",
112        min_children: 1,
113        max_children: 4,
114        keywords: &[],
115        executable_now: true,
116    },
117    PlanCombinator {
118        name: "cache",
119        min_children: 1,
120        max_children: 1,
121        keywords: &["mode", "ttl"],
122        executable_now: true,
123    },
124    PlanCombinator {
125        name: "budget",
126        min_children: 1,
127        max_children: 1,
128        keywords: &["max-cost", "max-latency-ms", "max-tokens"],
129        executable_now: true,
130    },
131    PlanCombinator {
132        name: "local",
133        min_children: 1,
134        max_children: 1,
135        keywords: &[],
136        executable_now: true,
137    },
138    PlanCombinator {
139        name: "remote",
140        min_children: 1,
141        max_children: 1,
142        keywords: &[],
143        executable_now: true,
144    },
145    PlanCombinator {
146        name: "trace",
147        min_children: 1,
148        max_children: 1,
149        keywords: &[],
150        executable_now: true,
151    },
152];