1use serde::Deserialize;
3
4#[derive(Debug, Clone, Deserialize)]
5pub struct PipelineDef {
6 pub pipeline: String,
7 #[serde(default)]
8 pub budget: Option<BudgetDef>,
9 pub steps: Vec<StepDef>,
10}
11
12#[derive(Debug, Clone, Deserialize)]
15#[serde(untagged)]
16pub enum ArmDef {
17 Name(String),
19 Step {
21 step: String,
22 #[serde(default)]
23 handler: Option<String>,
24 #[serde(default)]
25 args: Option<serde_json::Value>,
26 },
27}
28
29impl ArmDef {
30 pub fn label(&self) -> &str {
32 match self {
33 ArmDef::Name(n) => n,
34 ArmDef::Step { step, .. } => step,
35 }
36 }
37
38 pub fn handler_name(&self) -> &str {
40 match self {
41 ArmDef::Name(n) => n,
42 ArmDef::Step { step, handler, .. } => handler.as_deref().unwrap_or(step),
43 }
44 }
45
46 pub fn args(&self) -> Option<&serde_json::Value> {
48 match self {
49 ArmDef::Name(_) => None,
50 ArmDef::Step { args, .. } => args.as_ref(),
51 }
52 }
53}
54
55#[derive(Debug, Clone, Deserialize)]
56#[serde(untagged)]
57pub enum BudgetDef {
58 Tokens { tokens: u64 },
59 Calls { calls: u64 },
60 Duration { duration_ms: u64 },
61 CostCents { cost_cents: u64 },
62}
63
64#[derive(Debug, Clone, Deserialize)]
65#[serde(untagged)]
66pub enum StepDef {
67 Step(StepNode),
68 Delegate(DelegateNode),
69 Pipe(PipeNode),
70 JoinAll(JoinAllNode),
71 RouteOnConfidence(RouteNode),
72 Speculate(SpeculateNode),
73}
74
75#[derive(Debug, Clone, Deserialize)]
76pub struct StepNode {
77 pub step: String,
78 #[serde(default)]
79 pub handler: Option<String>,
80 #[serde(default)]
81 pub args: Option<serde_json::Value>,
82}
83
84#[derive(Debug, Clone, Deserialize)]
85pub struct DelegateNode {
86 pub delegate: String,
87 #[serde(default)]
88 pub name: Option<String>,
89 #[serde(default)]
90 pub budget: Option<BudgetDef>,
91}
92
93#[derive(Debug, Clone, Deserialize)]
94pub struct PipeNode {
95 pub pipe: String,
96 pub stages: Vec<ArmDef>,
97}
98
99#[derive(Debug, Clone, Deserialize)]
100pub struct JoinAllNode {
101 pub join_all: String,
102 pub arms: Vec<ArmDef>,
103}
104
105#[derive(Debug, Clone, Deserialize)]
106pub struct RouteNode {
107 pub route_on_confidence: String,
108 pub value: String,
109 pub routes: Vec<RouteBranch>,
110}
111
112#[derive(Debug, Clone, Deserialize)]
113pub struct RouteBranch {
114 pub range: String,
115 pub label: String,
116 pub handler: String,
117 #[serde(default)]
118 pub args: Option<serde_json::Value>,
119}
120
121#[derive(Debug, Clone, Deserialize)]
122pub struct SpeculateNode {
123 pub speculate: String,
124 #[serde(default = "default_speculate_mode")]
125 pub mode: SpeculateMode,
126 pub arms: Vec<ArmDef>,
127}
128
129#[derive(Debug, Clone, Deserialize, Default)]
130#[serde(rename_all = "snake_case")]
131pub enum SpeculateMode {
132 #[default]
133 PickBest,
134 FirstOk,
135}
136
137fn default_speculate_mode() -> SpeculateMode {
138 SpeculateMode::PickBest
139}