-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathasana_tools.py
317 lines (242 loc) · 13.8 KB
/
asana_tools.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# NOTE:
# - This section defines the Asana tools to be utilized by the agent.
# - Pydantic AI tools offer multiple flavors for defining tools: `plan` (decorator), `context` (decorator), and `tool definition`. See the documentation: https://ai.pydantic.dev/tools/
# - For this example, I opted for the `tool definition` flavor because it is loosely coupled to the agent until runtime.
# This approach ensures flexibility, allowing the tools to be reused by various Asana agents (e.g., Console, Streamlit, etc.).
import json
from typing import List
from pydantic_ai.tools import Tool
from asana_api import Asana_Api, AsanaProject, AsanaTask, AsanaTaskUpdate
class AsanaTools:
def __init__(self):
self.__asana__ = Asana_Api()
self.__tools__ : List[Tool] = []
# project related tools
self.__tools__.append(Tool(name = "create_project", function = self.create_project, description="Creates a project by name"))
self.__tools__.append(Tool(name = "get_project_id", function = self.get_project_id, description="Gets a project id by project name"))
self.__tools__.append(Tool(name = "get_project_by_id", function = self.get_project_by_id, description="Gets a project object by project id"))
self.__tools__.append(Tool(name = "get_project_by_name", function = self.get_project_by_name, description="Gets a project object by project name"))
self.__tools__.append(Tool(name = "get_projects", function = self.get_projects, description="Gets all existing project objects. Takes no arguments."))
self.__tools__.append(Tool(name = "update_project", function = self.update_project, description="Updates an existing project object for a given project id"))
self.__tools__.append(Tool(name = "delete_project_by_id", function = self.delete_project_by_id, description="Deletes an existing project object by project id"))
self.__tools__.append(Tool(name = "delete_project", function = self.delete_project, description="Deletes an existing project object by project name"))
# task related tools
self.__tools__.append(Tool(name = "create_task", function = self.create_task, description="Creates a task by name for a given project id"))
self.__tools__.append(Tool(name = "get_task_by_id", function = self.get_task_by_id, description="Gets a task by task id"))
self.__tools__.append(Tool(name = "get_task_by_name", function = self.get_task_by_name, description="Gets a task for a given project using the project name and task name"))
self.__tools__.append(Tool(name = "get_tasks_by_project_id", function = self.get_tasks_by_project_id, description="Gets all existing task objects for a given project id"))
self.__tools__.append(Tool(name = "get_tasks_by_project_name", function = self.get_tasks_by_project_name, description="Gets all existing task objects for a given project name"))
self.__tools__.append(Tool(name = "update_task_status", function = self.update_task_status, description="Updates an existing task object's status for a given task id"))
self.__tools__.append(Tool(name = "update_task", function = self.update_task, description="Updates an existing task object for a given task id"))
self.__tools__.append(Tool(name = "delete_task_by_id", function = self.delete_task_by_id, description="Deletes an existing task object by task id"))
self.__tools__.append(Tool(name = "delete_task_by_name", function = self.delete_task_by_name, description="Deletes an existing task object for a given project name and for a given task name"))
#----------------------#
# PROJECTS #
#----------------------#
def create_project(self, project_name: str) -> AsanaProject:
"""
Creates a project by name.
Example call: create_project("Test Project")
Args:
project_name (str): The name of the project to create.
Returns:
AsanaProject: A project object that was created or an error message if the API call threw an error.
"""
return self.__asana__.create_project(project_name)
def get_project_id(self, project_name: str) -> str:
"""
Gets a project id by project name.
Example call: get_project_id("Test Project")
Args:
project_name (str): The name of the project to get the project id.
Returns:
str: A project id if it exists, else None if not found, or an error message if the API call threw an error.
"""
project_id = self.__asana__.get_project_id(project_name)
return project_id
def get_project_by_id(self, project_id: str) -> AsanaProject:
"""
Gets a project object by project id.
Example call: get_project_by_id("Project Id")
Args:
project_id (str): The the project id to get the project object.
Returns:
AsanaProject: A project object if it exists, else None if not found, or an error message if the API call threw an error.
"""
project = self.__asana__.get_project_by_id(project_id)
return project
def get_project_by_name(self, project_name: str) -> AsanaProject:
"""
Gets a project object by project name.
Example call: get_project_by_name("Project name")
Args:
project_name (str): The the project name to get the project object.
Returns:
AsanaProject: A project object if it exists, else None if not found, or an error message if the API call threw an error.
"""
project = self.__asana__.get_project_by_name(project_name)
return project
def get_projects(self) -> List[AsanaProject]:
"""
Gets all existing project objects.
Example call: get_projects()
Returns:
List[AsanaProject]: A list of project objects if any, or an error message if the API call threw an error.
"""
projects = self.__asana__.get_projects()
return projects
def update_project(self, project_id: str, model: AsanaProject) -> AsanaProject:
"""
Updates an existing project object for a given project id.
Example call: update_project("Project Id", model)
Args:
project_id (str): The project id to update the project object.
model (AsanaProject): A json representation of a model with the following properties:
{
"name": "(str) The name of the project to update"
}
Returns:
AsanaProject: Updated project object if successful, else None if not found, or an error message if the API call threw an error.
"""
project = self.__asana__.update_project(project_id, model)
return project
def delete_project_by_id(self, project_id: str) -> bool:
"""
Deletes an existing project object by project id.
Example call: delete_project_by_id("Project Id")
Args:
project_id (str): The project id to delete an existing project object.
Returns:
bool: True if deleted, else false not found, or an error message if the API call threw an error.
"""
result = self.__asana__.delete_project_by_id(project_id)
return result
def delete_project(self, project_name: str) -> bool:
"""
Deletes an existing project object by project name.
Example call: delete_project("Project Name")
Args:
project_name (str): The project name to delete the project object.
Returns:
bool: True if deleted, else false not found, or an error message if the API call threw an error.
"""
result = self.__asana__.delete_project(project_name)
return result
#----------------------#
# TASKS #
#----------------------#
def create_task(self, project_id: str, task_name: str, due_date: str = None, status: str = "Not Started") -> AsanaTask:
"""
Creates a task by name for a given project id.
Example call: create_task("Project Id", "Test Task", "2021-12-31", "Not Started")
Args:
task_name (str): The task name to create.
project_id (str): The project id to create the task under.
due_date (str): The date the task is due in the format YYYY-MM-DD. If not given, the current day is used.
status (str): The status of the task. Possible values: ['Not Started', 'In Progress', 'Completed']. Default is 'Not Started'.
Returns:
AsanaTask: created task object if successful, or an error message if the API call threw an error.
"""
task = self.__asana__.create_task(project_id, task_name, due_date, status)
return task
def get_task_by_id(self, task_id: str) -> AsanaTask:
"""
Gets a task by task id.
Example call: get_task_by_id("Task Id")
Args:
task_id (str): The task id to get the task object.
Returns:
AsanaTask: task object if it exists, else None if not found, or an error message if the API call threw an error.
"""
task = self.__asana__.get_task_by_id(task_id)
return task
def get_task_by_name(self, project_name: str, name: str) -> AsanaTask:
"""
Gets a task for a given project using the project name and task name.
Example call: get_task_by_name("Project Name", "Task Name")
Args:
project_name (str): The project name where the task belongs too.
name (str): The task name get to get the task object.
Returns:
AsanaTask: task object if it exists, else None if not found, or an error message if the API call threw an error.
"""
task = self.__asana__.get_task_by_name(project_name, name)
return task
def get_tasks_by_project_id(self, project_id: str) -> List[AsanaTask]:
"""
Gets all existing task objects for a given project id.
Example call: get_tasks_by_project_id("Project Id")
Args:
project_id (str): The project id where to get task objects.
Returns:
list(AsanaTask): A list of tasks objects if any, or an error message if the API call threw an error.
"""
tasks = self.__asana__.get_tasks_by_project_id(project_id)
return tasks
def get_tasks_by_project_name(self, project_name: str) -> List[AsanaTask]:
"""
Gets all existing task objects for a given project name.
Example call: get_tasks_by_project_name("Project Name")
Args:
project_name (str): The project name where to get task objects.
Returns:
list(AsanaTask): A list of tasks objects if any, or an error message if the API call threw an error.
"""
tasks = self.__asana__.get_tasks_by_project_name(project_name)
return tasks
def update_task_status(self, task_id: str, status: str) -> bool:
"""
Updates an existing task object's status for a given task id.
Example call: update_task_status("Task Id", "Completed")
Args:
task_id (str): The task id to update the task object's status.
status (str): The status to update the task status. Possible values: ['Not Started', 'In Progress, 'Completed'].
Returns:
bool: Updated of true else false if not found, or an error message if the API call threw an error.
"""
result = self.__asana__.update_task_status(task_id, status)
return result
def update_task(self, task_id: str, model: str) -> AsanaTask:
"""
Updates an existing task object for a given task id.
Example call: update_task("Task Id", model)
Args:
task_id (str): The task id used to update the task object.
model (str): A json representation of a model with the following properties:
{
"name": "(str) The name of the task to update.",
"due_date": "(str) The due_date of the task to update.",
"status": "(str) The status of the task to update. Valid Status: ['Not Started', 'In Progress', 'Completed']",
}
Returns:
AsanaTask: Updated task object if successful, else None if not found, or an error message if the API call threw an error.
"""
data_model = json.loads(model)
update_model = AsanaTaskUpdate(**data_model)
project = self.__asana__.update_task(task_id, update_model)
return project
def delete_task_by_id(self, task_id: str) -> bool:
"""
Deletes an existing task object by task id.
Example call: delete_task_by_id("Task Id")
Args:
task_id (str): The task id to delete an existing task object.
Returns:
bool: True if deleted, else False if not found, or an error message if the API call threw an error.
"""
result = self.__asana__.delete_task_by_id(task_id)
return result
def delete_task_by_name(self, project_name: str, name: str) -> bool:
"""
Deletes an existing task object for a given project name and for a given task name.
Example call: delete_task_by_name("Project Name", "Task Id")
Args:
project_name (str): The project name where the task belongs too.
name (str): The task name used to delete an existing task object.
Returns:
bool: True if deleted, else False if not found, or an error message if the API call threw an error.
"""
result = self.__asana__.delete_task_by_name(project_name, name)
return result
def get_tools(self) -> List[Tool]:
return self.__tools__