Skip to main content

bamboo_engine/runtime/task_context/
conversion.rs

1use bamboo_domain::{TaskItem, TaskItemStatus, TaskList};
2
3use super::{TaskLoopContext, TaskLoopItem};
4
5impl TaskLoopContext {
6    /// Create `TaskLoopContext` from the session's task list.
7    pub fn from_session(session: &bamboo_agent_core::Session) -> Option<Self> {
8        session.task_list.as_ref().map(|task_list| {
9            // Preserve version from existing task_list metadata if available.
10            // This prevents version reset across multiple executions.
11            let existing_version = session
12                .metadata
13                .get("task_list_version")
14                .or_else(|| session.metadata.get("todo_list_version"))
15                .and_then(|v| v.parse::<u64>().ok())
16                .unwrap_or(0);
17
18            let items: Vec<TaskLoopItem> = task_list
19                .items
20                .iter()
21                .map(|item| TaskLoopItem {
22                    id: item.id.clone(),
23                    description: item.description.clone(),
24                    status: item.status.clone(),
25                    depends_on: item.depends_on.clone(),
26                    notes: item.notes.clone(),
27                    active_form: item.active_form.clone(),
28                    parent_id: item.parent_id.clone(),
29                    phase: item.phase.clone(),
30                    priority: item.priority.clone(),
31                    completion_criteria: item.completion_criteria.clone(),
32                    evidence: item.evidence.clone(),
33                    blockers: item.blockers.clone(),
34                    transitions: item.transitions.clone(),
35                    tool_calls: Vec::new(),
36                    started_at_round: item
37                        .transitions
38                        .iter()
39                        .find(|transition| {
40                            matches!(transition.to_status, TaskItemStatus::InProgress)
41                        })
42                        .and_then(|transition| transition.round),
43                    completed_at_round: item
44                        .transitions
45                        .iter()
46                        .rev()
47                        .find(|transition| {
48                            matches!(transition.to_status, TaskItemStatus::Completed)
49                        })
50                        .and_then(|transition| transition.round),
51                })
52                .collect();
53
54            Self {
55                session_id: task_list.session_id.clone(),
56                active_item_id: items
57                    .iter()
58                    .find(|item| matches!(item.status, TaskItemStatus::InProgress))
59                    .map(|item| item.id.clone()),
60                items,
61                current_round: 0,
62                max_rounds: 200,
63                created_at: task_list.created_at,
64                updated_at: task_list.updated_at,
65                version: existing_version,
66            }
67        })
68    }
69
70    /// Convert back to `TaskList` for persistence.
71    pub fn into_task_list(self) -> TaskList {
72        TaskList {
73            session_id: self.session_id,
74            title: "Agent Tasks".to_string(),
75            items: self
76                .items
77                .into_iter()
78                .map(|loop_item| TaskItem {
79                    id: loop_item.id,
80                    description: loop_item.description,
81                    status: loop_item.status,
82                    depends_on: loop_item.depends_on,
83                    notes: loop_item.notes,
84                    active_form: loop_item.active_form,
85                    parent_id: loop_item.parent_id,
86                    phase: loop_item.phase,
87                    priority: loop_item.priority,
88                    completion_criteria: loop_item.completion_criteria,
89                    evidence: loop_item.evidence,
90                    blockers: loop_item.blockers,
91                    transitions: loop_item.transitions,
92                })
93                .collect(),
94            created_at: self.created_at,
95            updated_at: self.updated_at,
96        }
97    }
98}