2
2
3
3
import uuid
4
4
from dataclasses import dataclass , field
5
- from datetime import datetime
6
5
from enum import Enum
7
- from typing import Any , Literal
6
+ from typing import Any , Literal , Callable
8
7
9
8
10
9
class TaskStatus (str , Enum ):
@@ -40,52 +39,33 @@ def advance_to_next(self):
40
39
"""Move to next task."""
41
40
self .current_index += 1
42
41
43
-
44
- # Storage - just one todo list per agent run
45
- _current_todo : TodoList | None = None
46
-
47
- def todo_manager (
48
- action : Literal ["create" , "get_current" , "start_task" , "complete_task" , "get_final_summary" ],
49
- tasks : list [str ] | None = None ,
50
- summary : str | None = None ,
51
- ) -> dict [str , Any ]:
52
- """
53
- Simplified todo manager for agent runs.
54
-
55
- Actions:
56
- - create: Create todo list with tasks
57
- - get_current: Get current task to work on
58
- - start_task: Mark current task as in progress
59
- - complete_task: Complete current task with summary
60
- - get_final_summary: Get all completed work
61
- """
62
- global _current_todo
63
-
64
- if action == "create" :
65
- if not tasks :
42
+ def create_tasks (self , task_descriptions : list [str ]) -> dict [str , Any ]:
43
+ """Create tasks from descriptions."""
44
+ if not task_descriptions :
66
45
raise ValueError ("Tasks required for create action" )
67
46
68
- _current_todo = TodoList ()
69
- for i , desc in enumerate (tasks ):
47
+ # Clear existing tasks
48
+ self .tasks .clear ()
49
+ self .current_index = 0
50
+
51
+ for i , desc in enumerate (task_descriptions ):
70
52
task = Task (
71
53
id = str (uuid .uuid4 ()),
72
54
description = desc .strip (),
73
55
order = i
74
56
)
75
- _current_todo .tasks .append (task )
57
+ self .tasks .append (task )
76
58
77
59
return {
78
60
"action" : "create" ,
79
- "tasks" : [{"id" : t .id , "description" : t .description , "order" : t .order } for t in _current_todo .tasks ],
80
- "total_count" : len (_current_todo .tasks ),
81
- "message" : f"Created { len (tasks )} tasks"
61
+ "tasks" : [{"id" : t .id , "description" : t .description , "order" : t .order } for t in self .tasks ],
62
+ "total_count" : len (self .tasks ),
63
+ "message" : f"Created { len (task_descriptions )} tasks"
82
64
}
83
65
84
- if not _current_todo :
85
- raise ValueError ("No todo list exists. Create one first." )
86
-
87
- if action == "get_current" :
88
- current = _current_todo .get_current_task ()
66
+ def get_current (self ) -> dict [str , Any ]:
67
+ """Get current task information."""
68
+ current = self .get_current_task ()
89
69
if not current :
90
70
return {
91
71
"action" : "get_current" ,
@@ -97,12 +77,13 @@ def todo_manager(
97
77
return {
98
78
"action" : "get_current" ,
99
79
"current_task" : {"id" : current .id , "description" : current .description , "status" : current .status .value },
100
- "progress" : f"{ _current_todo .current_index + 1 } /{ len (_current_todo .tasks )} " ,
80
+ "progress" : f"{ self .current_index + 1 } /{ len (self .tasks )} " ,
101
81
"message" : f"Current task: { current .description } "
102
82
}
103
83
104
- elif action == "start_task" :
105
- current = _current_todo .get_current_task ()
84
+ def start_current_task (self ) -> dict [str , Any ]:
85
+ """Start the current task."""
86
+ current = self .get_current_task ()
106
87
if not current :
107
88
raise ValueError ("No current task to start" )
108
89
@@ -113,11 +94,12 @@ def todo_manager(
113
94
"message" : f"Started task: { current .description } "
114
95
}
115
96
116
- elif action == "complete_task" :
97
+ def complete_current_task (self , summary : str ) -> dict [str , Any ]:
98
+ """Complete the current task with summary."""
117
99
if not summary :
118
100
raise ValueError ("Summary required for complete_task" )
119
101
120
- current = _current_todo .get_current_task ()
102
+ current = self .get_current_task ()
121
103
if not current :
122
104
raise ValueError ("No current task to complete" )
123
105
@@ -126,22 +108,23 @@ def todo_manager(
126
108
127
109
current .status = TaskStatus .COMPLETED
128
110
current .summary = summary .strip ()
129
- _current_todo .advance_to_next ()
111
+ self .advance_to_next ()
130
112
131
- next_task = _current_todo .get_current_task ()
132
- completed_count = sum (1 for t in _current_todo .tasks if t .status == TaskStatus .COMPLETED )
113
+ next_task = self .get_current_task ()
114
+ completed_count = sum (1 for t in self .tasks if t .status == TaskStatus .COMPLETED )
133
115
134
116
return {
135
117
"action" : "complete_task" ,
136
118
"completed_task" : {"id" : current .id , "description" : current .description , "summary" : current .summary },
137
119
"next_task" : {"id" : next_task .id , "description" : next_task .description } if next_task else None ,
138
- "progress" : f"{ completed_count } /{ len (_current_todo .tasks )} " ,
120
+ "progress" : f"{ completed_count } /{ len (self .tasks )} " ,
139
121
"all_completed" : next_task is None ,
140
122
"message" : f"Completed: { current .description } "
141
123
}
142
124
143
- elif action == "get_final_summary" :
144
- completed_tasks = [t for t in _current_todo .tasks if t .status == TaskStatus .COMPLETED ]
125
+ def get_final_summary (self ) -> dict [str , Any ]:
126
+ """Get comprehensive final summary of all completed work."""
127
+ completed_tasks = [t for t in self .tasks if t .status == TaskStatus .COMPLETED ]
145
128
146
129
if not completed_tasks :
147
130
return {
@@ -160,18 +143,55 @@ def todo_manager(
160
143
161
144
final_summary = "\n \n " .join (final_content )
162
145
163
- # Clean up after getting final summary
164
- _current_todo = None
165
-
166
146
return {
167
147
"action" : "get_final_summary" ,
168
148
"final_summary" : final_summary ,
169
149
"total_completed" : len (completed_tasks ),
170
150
"message" : f"Final summary with { len (completed_tasks )} completed tasks."
171
151
}
172
152
173
- else :
174
- raise ValueError (f"Unknown action: { action } " )
153
+
154
+ def create_todo_manager (todo_list : TodoList ) -> Callable [..., dict [str , Any ]]:
155
+ """
156
+ Create a todo_manager function bound to a specific TodoList instance.
157
+
158
+ This allows each agent to have its own isolated todo list.
159
+
160
+ Args:
161
+ todo_list: The TodoList instance to bind to
162
+
163
+ Returns:
164
+ A todo_manager function that operates on the provided TodoList
165
+ """
166
+ def todo_manager (
167
+ action : Literal ["create" , "get_current" , "start_task" , "complete_task" , "get_final_summary" ],
168
+ tasks : list [str ] | None = None ,
169
+ summary : str | None = None ,
170
+ ) -> dict [str , Any ]:
171
+ """
172
+ Todo manager bound to a specific TodoList instance.
173
+
174
+ Actions:
175
+ - create: Create todo list with tasks
176
+ - get_current: Get current task to work on
177
+ - start_task: Mark current task as in progress
178
+ - complete_task: Complete current task with summary
179
+ - get_final_summary: Get all completed work
180
+ """
181
+ if action == "create" :
182
+ return todo_list .create_tasks (tasks or [])
183
+ elif action == "get_current" :
184
+ return todo_list .get_current ()
185
+ elif action == "start_task" :
186
+ return todo_list .start_current_task ()
187
+ elif action == "complete_task" :
188
+ return todo_list .complete_current_task (summary or "" )
189
+ elif action == "get_final_summary" :
190
+ return todo_list .get_final_summary ()
191
+ else :
192
+ raise ValueError (f"Unknown action: { action } " )
193
+
194
+ return todo_manager
175
195
176
196
177
197
def get_todo_instruction_tpl (task_range : tuple [int , int ] = (3 , 5 )) -> str :
@@ -196,4 +216,4 @@ def get_todo_instruction_tpl(task_range: tuple[int, int] = (3, 5)) -> str:
196
216
197
217
IMPORTANT: Task summaries should be DETAILED and COMPREHENSIVE (3-5 sentences).
198
218
Include specific information, recommendations, and actionable details.
199
- """
219
+ """
0 commit comments