bamboo_engine/runtime/task_context/
conversion.rs1use bamboo_domain::{TaskItem, TaskItemStatus, TaskList};
2
3use super::{TaskLoopContext, TaskLoopItem};
4
5fn clone_loop_item_into_task_item(loop_item: &TaskLoopItem) -> TaskItem {
6 TaskItem {
7 id: loop_item.id.clone(),
8 description: loop_item.description.clone(),
9 status: loop_item.status.clone(),
10 depends_on: loop_item.depends_on.clone(),
11 notes: loop_item.notes.clone(),
12 active_form: loop_item.active_form.clone(),
13 parent_id: loop_item.parent_id.clone(),
14 phase: loop_item.phase.clone(),
15 priority: loop_item.priority.clone(),
16 completion_criteria: loop_item.completion_criteria.clone(),
17 evidence: loop_item.evidence.clone(),
18 blockers: loop_item.blockers.clone(),
19 transitions: loop_item.transitions.clone(),
20 }
21}
22
23fn into_task_item(loop_item: TaskLoopItem) -> TaskItem {
24 TaskItem {
25 id: loop_item.id,
26 description: loop_item.description,
27 status: loop_item.status,
28 depends_on: loop_item.depends_on,
29 notes: loop_item.notes,
30 active_form: loop_item.active_form,
31 parent_id: loop_item.parent_id,
32 phase: loop_item.phase,
33 priority: loop_item.priority,
34 completion_criteria: loop_item.completion_criteria,
35 evidence: loop_item.evidence,
36 blockers: loop_item.blockers,
37 transitions: loop_item.transitions,
38 }
39}
40
41impl TaskLoopContext {
42 pub fn from_session(session: &bamboo_agent_core::Session) -> Option<Self> {
44 session.task_list.as_ref().map(|task_list| {
45 let existing_version = session
48 .task_list_version_meta()
49 .or_else(|| session.todo_list_version_meta())
50 .and_then(|v| v.parse::<u64>().ok())
51 .unwrap_or(0);
52
53 let items: Vec<TaskLoopItem> = task_list
54 .items
55 .iter()
56 .map(|item| TaskLoopItem {
57 id: item.id.clone(),
58 description: item.description.clone(),
59 status: item.status.clone(),
60 depends_on: item.depends_on.clone(),
61 notes: item.notes.clone(),
62 active_form: item.active_form.clone(),
63 parent_id: item.parent_id.clone(),
64 phase: item.phase.clone(),
65 priority: item.priority.clone(),
66 completion_criteria: item.completion_criteria.clone(),
67 evidence: item.evidence.clone(),
68 blockers: item.blockers.clone(),
69 transitions: item.transitions.clone(),
70 tool_calls: Vec::new(),
71 started_at_round: item
72 .transitions
73 .iter()
74 .find(|transition| {
75 matches!(transition.to_status, TaskItemStatus::InProgress)
76 })
77 .and_then(|transition| transition.round),
78 completed_at_round: item
79 .transitions
80 .iter()
81 .rev()
82 .find(|transition| {
83 matches!(transition.to_status, TaskItemStatus::Completed)
84 })
85 .and_then(|transition| transition.round),
86 })
87 .collect();
88
89 Self {
90 session_id: task_list.session_id.clone(),
91 active_item_id: items
92 .iter()
93 .find(|item| matches!(item.status, TaskItemStatus::InProgress))
94 .map(|item| item.id.clone()),
95 items,
96 current_round: 0,
97 max_rounds: 200,
98 created_at: task_list.created_at,
99 updated_at: task_list.updated_at,
100 version: existing_version,
101 task_list_dirty: false,
102 }
103 })
104 }
105
106 pub fn to_task_list_with_title(&self, title: impl Into<String>) -> TaskList {
108 TaskList {
109 session_id: self.session_id.clone(),
110 title: title.into(),
111 items: self
112 .items
113 .iter()
114 .map(clone_loop_item_into_task_item)
115 .collect(),
116 created_at: self.created_at,
117 updated_at: self.updated_at,
118 }
119 }
120
121 pub fn into_task_list(self) -> TaskList {
123 self.into_task_list_with_title("Agent Tasks")
124 }
125
126 pub fn into_task_list_with_title(self, title: impl Into<String>) -> TaskList {
128 TaskList {
129 session_id: self.session_id,
130 title: title.into(),
131 items: self.items.into_iter().map(into_task_item).collect(),
132 created_at: self.created_at,
133 updated_at: self.updated_at,
134 }
135 }
136}