tiphys.tools.scheduler
Scheduler tools for the agent.
Allows the agent to schedule, list, and manage background tasks.
1""" 2Scheduler tools for the agent. 3 4Allows the agent to schedule, list, and manage background tasks. 5""" 6 7from typing import TYPE_CHECKING, Literal 8 9from pydantic import BaseModel, Field 10 11from tiphys.context import get_context 12from tiphys.scheduler.models import ScheduleType 13from tiphys.tools.base import tool 14 15if TYPE_CHECKING: 16 from tiphys.scheduler.service import TaskScheduler 17 18 19def _get_scheduler() -> "TaskScheduler": 20 """Get the task scheduler from the application context.""" 21 context = get_context() 22 if not context.scheduler: 23 raise RuntimeError("Task scheduler is not available in the current context") 24 return context.scheduler 25 26 27class ScheduleTaskArgs(BaseModel): 28 """Arguments for scheduling a task.""" 29 30 name: str = Field(..., description="A short, descriptive name for the task") 31 prompt: str = Field(..., description="The instruction or prompt for the agent to execute") 32 schedule_type: Literal["cron", "interval", "once"] = Field( 33 ..., description="Type of schedule: 'cron', 'interval', or 'once'" 34 ) 35 schedule_value: str = Field( 36 ..., 37 description="The schedule value (e.g., '*/5 * * * *' for cron, '300' for interval seconds, or ISO timestamp for once)", 38 ) 39 40 41@tool(name="schedule_task", description="Schedule a new background task for the agent") 42async def schedule_task( 43 name: str, 44 prompt: str, 45 schedule_type: Literal["cron", "interval", "once"], 46 schedule_value: str, 47) -> str: 48 """ 49 Schedule a task to run automatically. 50 51 Examples: 52 - cron: "0 9 * * *" (Every day at 9 AM) 53 - interval: "3600" (Every hour) 54 - once: "2023-12-31T23:59:59" (Specific time) 55 """ 56 scheduler = _get_scheduler() 57 58 # Map string type to Enum 59 type_map = { 60 "cron": ScheduleType.CRON, 61 "interval": ScheduleType.INTERVAL, 62 "once": ScheduleType.ONCE, 63 } 64 65 try: 66 task_id = await scheduler.create_task( 67 name=name, 68 group="main", # TODO: In multi-tenant, use current group/user 69 prompt=prompt, 70 schedule_type=type_map[schedule_type], 71 schedule_value=schedule_value, 72 ) 73 return f"Task '{name}' scheduled successfully with ID: {task_id}" 74 except Exception as e: 75 return f"Failed to schedule task: {str(e)}" 76 77 78class ListTasksArgs(BaseModel): 79 """Arguments for listing tasks.""" 80 81 status: Literal["active", "paused", "completed", "all"] = Field( 82 "active", description="Filter tasks by status" 83 ) 84 85 86@tool(name="list_tasks", description="List scheduled tasks") 87async def list_tasks(status: str = "active") -> str: 88 """List tasks currently managed by the scheduler.""" 89 scheduler = _get_scheduler() 90 91 tasks = scheduler.store.list_all() 92 93 if status != "all": 94 tasks = [t for t in tasks if t.status == status] 95 96 if not tasks: 97 return f"No {status} tasks found." 98 99 lines = [f"Found {len(tasks)} {status} tasks:"] 100 for t in tasks: 101 next_run = t.next_run.isoformat() if t.next_run else "N/A" 102 lines.append(f"- [{t.status.value}] {t.name} (ID: {t.id})") 103 lines.append(f" Type: {t.schedule_type.value}, Value: {t.schedule_value}") 104 lines.append(f" Next Run: {next_run}") 105 lines.append("") 106 107 return "\n".join(lines) 108 109 110class ManageTaskArgs(BaseModel): 111 """Arguments for managing a task.""" 112 113 task_id: str = Field(..., description="The ID of the task to manage") 114 115 116@tool(name="delete_task", description="Delete a scheduled task") 117async def delete_task(task_id: str) -> str: 118 """Delete a task permanently.""" 119 scheduler = _get_scheduler() 120 121 if scheduler.store.delete(task_id): 122 return f"Task {task_id} deleted successfully." 123 return f"Task {task_id} not found." 124 125 126@tool(name="pause_task", description="Pause a scheduled task") 127async def pause_task(task_id: str) -> str: 128 """Pause a running task.""" 129 scheduler = _get_scheduler() 130 131 if await scheduler.pause_task(task_id): 132 return f"Task {task_id} paused." 133 return f"Task {task_id} not found." 134 135 136@tool(name="resume_task", description="Resume a paused task") 137async def resume_task(task_id: str) -> str: 138 """Resume a paused task.""" 139 scheduler = _get_scheduler() 140 141 if await scheduler.resume_task(task_id): 142 return f"Task {task_id} resumed." 143 return f"Task {task_id} not found."
class
ScheduleTaskArgs(pydantic.main.BaseModel):
28class ScheduleTaskArgs(BaseModel): 29 """Arguments for scheduling a task.""" 30 31 name: str = Field(..., description="A short, descriptive name for the task") 32 prompt: str = Field(..., description="The instruction or prompt for the agent to execute") 33 schedule_type: Literal["cron", "interval", "once"] = Field( 34 ..., description="Type of schedule: 'cron', 'interval', or 'once'" 35 ) 36 schedule_value: str = Field( 37 ..., 38 description="The schedule value (e.g., '*/5 * * * *' for cron, '300' for interval seconds, or ISO timestamp for once)", 39 )
Arguments for scheduling a task.
@tool(name='schedule_task', description='Schedule a new background task for the agent')
async def
schedule_task( name: str, prompt: str, schedule_type: Literal['cron', 'interval', 'once'], schedule_value: str) -> str:
42@tool(name="schedule_task", description="Schedule a new background task for the agent") 43async def schedule_task( 44 name: str, 45 prompt: str, 46 schedule_type: Literal["cron", "interval", "once"], 47 schedule_value: str, 48) -> str: 49 """ 50 Schedule a task to run automatically. 51 52 Examples: 53 - cron: "0 9 * * *" (Every day at 9 AM) 54 - interval: "3600" (Every hour) 55 - once: "2023-12-31T23:59:59" (Specific time) 56 """ 57 scheduler = _get_scheduler() 58 59 # Map string type to Enum 60 type_map = { 61 "cron": ScheduleType.CRON, 62 "interval": ScheduleType.INTERVAL, 63 "once": ScheduleType.ONCE, 64 } 65 66 try: 67 task_id = await scheduler.create_task( 68 name=name, 69 group="main", # TODO: In multi-tenant, use current group/user 70 prompt=prompt, 71 schedule_type=type_map[schedule_type], 72 schedule_value=schedule_value, 73 ) 74 return f"Task '{name}' scheduled successfully with ID: {task_id}" 75 except Exception as e: 76 return f"Failed to schedule task: {str(e)}"
Schedule a task to run automatically.
Examples: - cron: "0 9 * * *" (Every day at 9 AM) - interval: "3600" (Every hour) - once: "2023-12-31T23:59:59" (Specific time)
class
ListTasksArgs(pydantic.main.BaseModel):
79class ListTasksArgs(BaseModel): 80 """Arguments for listing tasks.""" 81 82 status: Literal["active", "paused", "completed", "all"] = Field( 83 "active", description="Filter tasks by status" 84 )
Arguments for listing tasks.
@tool(name='list_tasks', description='List scheduled tasks')
async def
list_tasks(status: str = 'active') -> str:
87@tool(name="list_tasks", description="List scheduled tasks") 88async def list_tasks(status: str = "active") -> str: 89 """List tasks currently managed by the scheduler.""" 90 scheduler = _get_scheduler() 91 92 tasks = scheduler.store.list_all() 93 94 if status != "all": 95 tasks = [t for t in tasks if t.status == status] 96 97 if not tasks: 98 return f"No {status} tasks found." 99 100 lines = [f"Found {len(tasks)} {status} tasks:"] 101 for t in tasks: 102 next_run = t.next_run.isoformat() if t.next_run else "N/A" 103 lines.append(f"- [{t.status.value}] {t.name} (ID: {t.id})") 104 lines.append(f" Type: {t.schedule_type.value}, Value: {t.schedule_value}") 105 lines.append(f" Next Run: {next_run}") 106 lines.append("") 107 108 return "\n".join(lines)
List tasks currently managed by the scheduler.
class
ManageTaskArgs(pydantic.main.BaseModel):
111class ManageTaskArgs(BaseModel): 112 """Arguments for managing a task.""" 113 114 task_id: str = Field(..., description="The ID of the task to manage")
Arguments for managing a task.
@tool(name='delete_task', description='Delete a scheduled task')
async def
delete_task(task_id: str) -> str:
117@tool(name="delete_task", description="Delete a scheduled task") 118async def delete_task(task_id: str) -> str: 119 """Delete a task permanently.""" 120 scheduler = _get_scheduler() 121 122 if scheduler.store.delete(task_id): 123 return f"Task {task_id} deleted successfully." 124 return f"Task {task_id} not found."
Delete a task permanently.
@tool(name='pause_task', description='Pause a scheduled task')
async def
pause_task(task_id: str) -> str:
127@tool(name="pause_task", description="Pause a scheduled task") 128async def pause_task(task_id: str) -> str: 129 """Pause a running task.""" 130 scheduler = _get_scheduler() 131 132 if await scheduler.pause_task(task_id): 133 return f"Task {task_id} paused." 134 return f"Task {task_id} not found."
Pause a running task.
@tool(name='resume_task', description='Resume a paused task')
async def
resume_task(task_id: str) -> str:
137@tool(name="resume_task", description="Resume a paused task") 138async def resume_task(task_id: str) -> str: 139 """Resume a paused task.""" 140 scheduler = _get_scheduler() 141 142 if await scheduler.resume_task(task_id): 143 return f"Task {task_id} resumed." 144 return f"Task {task_id} not found."
Resume a paused task.