lc_agents/plan_execute/
plan.rs1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Default)]
7pub enum StepStatus {
8 #[default]
10 Pending,
11 Running,
13 Completed,
15 Failed {
17 error: String,
19 },
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct PlanStep {
25 pub id: usize,
27 pub description: String,
29 #[serde(default)]
31 pub status: StepStatus,
32 #[serde(default)]
34 pub result: Option<String>,
35}
36
37impl PlanStep {
38 pub fn new(id: usize, description: impl Into<String>) -> Self {
40 Self {
41 id,
42 description: description.into(),
43 status: StepStatus::Pending,
44 result: None,
45 }
46 }
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct Plan {
52 pub objective: String,
54 pub steps: Vec<PlanStep>,
56}
57
58impl Plan {
59 pub fn new(objective: impl Into<String>, steps: Vec<PlanStep>) -> Self {
61 Self {
62 objective: objective.into(),
63 steps,
64 }
65 }
66
67 pub fn from_descriptions(objective: impl Into<String>, descs: Vec<String>) -> Self {
69 let steps = descs
70 .into_iter()
71 .enumerate()
72 .map(|(i, d)| PlanStep::new(i, d))
73 .collect();
74 Self::new(objective, steps)
75 }
76
77 pub fn next_pending(&self) -> Option<&PlanStep> {
79 self.steps.iter().find(|s| s.status == StepStatus::Pending)
80 }
81
82 pub fn is_complete(&self) -> bool {
84 self.steps.iter().all(|s| s.status == StepStatus::Completed)
85 }
86
87 pub fn mark_completed(&mut self, id: usize, result: impl Into<String>) {
89 if let Some(s) = self.steps.iter_mut().find(|s| s.id == id) {
90 s.status = StepStatus::Completed;
91 s.result = Some(result.into());
92 }
93 }
94
95 pub fn mark_failed(&mut self, id: usize, error: impl Into<String>) {
97 if let Some(s) = self.steps.iter_mut().find(|s| s.id == id) {
98 s.status = StepStatus::Failed {
99 error: error.into(),
100 };
101 }
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108
109 #[test]
110 fn test_from_descriptions() {
111 let plan = Plan::from_descriptions("目标", vec!["步骤1".to_string(), "步骤2".to_string()]);
112 assert_eq!(plan.objective, "目标");
113 assert_eq!(plan.steps.len(), 2);
114 assert_eq!(plan.steps[0].id, 0);
115 assert_eq!(plan.steps[1].id, 1);
116 assert_eq!(plan.steps[0].status, StepStatus::Pending);
117 }
118
119 #[test]
120 fn test_next_pending() {
121 let mut plan = Plan::from_descriptions("obj", vec!["a".to_string(), "b".to_string()]);
122 assert_eq!(plan.next_pending().unwrap().id, 0);
123 plan.mark_completed(0, "result".to_string());
124 assert_eq!(plan.next_pending().unwrap().id, 1);
125 plan.mark_completed(1, "result".to_string());
126 assert!(plan.next_pending().is_none());
127 }
128
129 #[test]
130 fn test_is_complete() {
131 let mut plan = Plan::from_descriptions("obj", vec!["a".to_string(), "b".to_string()]);
132 assert!(!plan.is_complete());
133 plan.mark_completed(0, "r".to_string());
134 assert!(!plan.is_complete());
135 plan.mark_completed(1, "r".to_string());
136 assert!(plan.is_complete());
137 }
138
139 #[test]
140 fn test_mark_failed() {
141 let mut plan = Plan::from_descriptions("obj", vec!["a".to_string()]);
142 plan.mark_failed(0, "出错".to_string());
143 assert_eq!(
144 plan.steps[0].status,
145 StepStatus::Failed {
146 error: "出错".to_string()
147 }
148 );
149 assert!(!plan.is_complete());
150 }
151
152 #[test]
153 fn test_empty_plan_complete() {
154 let plan = Plan::from_descriptions("obj", vec![]);
155 assert!(plan.is_complete());
156 }
157}