use crate::budget::TokenBudget;
use crate::level::LoopLevel;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LoopSpec {
pub name: String,
pub intent: String,
pub level: LoopLevel,
pub cadence: String,
pub budget: TokenBudget,
pub maker_prompt: String,
pub checker_prompt: String,
pub action_kind: String,
}
impl LoopSpec {
pub fn new(name: impl Into<String>, intent: impl Into<String>, level: LoopLevel) -> Self {
Self {
name: name.into(),
intent: intent.into(),
level,
cadence: "daily 09:00".into(),
budget: TokenBudget::default(),
maker_prompt: String::new(),
checker_prompt: String::new(),
action_kind: "report".into(),
}
}
pub fn with_cadence(mut self, c: impl Into<String>) -> Self {
self.cadence = c.into();
self
}
pub fn with_budget(mut self, b: TokenBudget) -> Self {
self.budget = b;
self
}
pub fn with_maker_prompt(mut self, p: impl Into<String>) -> Self {
self.maker_prompt = p.into();
self
}
pub fn with_checker_prompt(mut self, p: impl Into<String>) -> Self {
self.checker_prompt = p.into();
self
}
pub fn with_action_kind(mut self, k: impl Into<String>) -> Self {
self.action_kind = k.into();
self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builder_roundtrips_through_json() {
let spec = LoopSpec::new(
"issue-triage",
"label and route new issues",
LoopLevel::L1Report,
)
.with_cadence("every 2h")
.with_action_kind("comment");
let json = serde_json::to_string(&spec).unwrap();
let back: LoopSpec = serde_json::from_str(&json).unwrap();
assert_eq!(back.name, "issue-triage");
assert_eq!(back.level, LoopLevel::L1Report);
assert_eq!(back.cadence, "every 2h");
assert_eq!(back.action_kind, "comment");
}
}