"""Scheduled-task tools (#170) — the agent programs its own cron. * ``create_scheduled_task`` — WRITE (a future write, confirmed once now). * ``list_scheduled_tasks`` — READ. * ``delete_scheduled_task`` — WRITE (removes a future side effect). * ``run_scheduled_task_now`` — WRITE (immediate side effect). """ from __future__ import annotations from typing import Any from backend import scheduler as _scheduler from backend.tools.context import ToolContext, ToolError, ToolRisk from backend.tools.registry import tool from backend.tools.schemas import ( CreateScheduledTaskInput, DeleteScheduledTaskInput, ListVaultsInput, RunScheduledTaskInput, ) @tool( name="create_scheduled_task", description="Program an automatic task (create_file, append_to_file, notify) on a cron-like schedule.", input_model=CreateScheduledTaskInput, risk=ToolRisk.WRITE, ) def create_scheduled_task(ctx: ToolContext, params: CreateScheduledTaskInput) -> dict[str, Any]: """Create a task owned by the requesting user.""" try: return _scheduler.create_task( params.name, params.action, params.schedule, created_by=ctx.username, ) except ValueError as e: raise ToolError(str(e), code="invalid_arguments") from e @tool( name="list_scheduled_tasks", description="List automatic tasks programmed in ObsiGate.", input_model=ListVaultsInput, risk=ToolRisk.READ, ) def list_scheduled_tasks(ctx: ToolContext, _params: ListVaultsInput) -> list[dict[str, Any]]: """Return tasks newest first.""" return _scheduler.list_tasks() @tool( name="delete_scheduled_task", description="Delete a programmed automatic task.", input_model=DeleteScheduledTaskInput, risk=ToolRisk.WRITE, ) def delete_scheduled_task(ctx: ToolContext, params: DeleteScheduledTaskInput) -> dict[str, Any]: """Delete by id; unknown id is a not_found tool error.""" if not _scheduler.delete_task(params.task_id): raise ToolError(f"Unknown task: {params.task_id}", code="not_found") return {"ok": True, "task_id": params.task_id} @tool( name="run_scheduled_task_now", description="Execute a programmed task immediately (manual run).", input_model=RunScheduledTaskInput, risk=ToolRisk.WRITE, ) def run_scheduled_task_now(ctx: ToolContext, params: RunScheduledTaskInput) -> dict[str, Any]: """Run now and return the outcome (failures are recorded + notified).""" try: return _scheduler.run_task(params.task_id, manual=True) except KeyError as e: raise ToolError(f"Unknown task: {params.task_id}", code="not_found") from e