Skip to main content

agentzero_tools/skills/
sop.rs

1use anyhow::{bail, Context};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
5pub struct SopStep {
6    pub title: String,
7    pub completed: bool,
8}
9
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
11pub struct SopPlan {
12    pub id: String,
13    pub steps: Vec<SopStep>,
14}
15
16pub fn create_plan(id: &str, steps: &[&str]) -> anyhow::Result<SopPlan> {
17    if id.trim().is_empty() {
18        bail!("sop id cannot be empty");
19    }
20    if steps.is_empty() {
21        bail!("sop requires at least one step");
22    }
23
24    let mapped = steps
25        .iter()
26        .map(|title| SopStep {
27            title: (*title).to_string(),
28            completed: false,
29        })
30        .collect::<Vec<_>>();
31
32    Ok(SopPlan {
33        id: id.to_string(),
34        steps: mapped,
35    })
36}
37
38pub fn advance_step(plan: &mut SopPlan, step_index: usize) -> anyhow::Result<()> {
39    let step = plan
40        .steps
41        .get_mut(step_index)
42        .with_context(|| format!("step index {step_index} is out of range"))?;
43
44    if step.completed {
45        bail!("step `{}` is already completed", step.title);
46    }
47
48    step.completed = true;
49    Ok(())
50}
51
52#[cfg(test)]
53mod tests {
54    use super::{advance_step, create_plan};
55
56    #[test]
57    fn advance_step_success_path() {
58        let mut plan = create_plan("deploy", &["build", "ship"]).expect("plan should create");
59        advance_step(&mut plan, 0).expect("advance should succeed");
60        assert!(plan.steps[0].completed);
61        assert!(!plan.steps[1].completed);
62    }
63
64    #[test]
65    fn advance_step_rejects_out_of_range_negative_path() {
66        let mut plan = create_plan("deploy", &["build"]).expect("plan should create");
67        let err = advance_step(&mut plan, 3).expect_err("out of range should fail");
68        assert!(err.to_string().contains("out of range"));
69    }
70}