import json from typing import Optional, Type from pydantic import BaseModel, Field from app.agent.tools.base import MoviePilotTool from app.agent.tools.tags import ToolTag from app.runtime.config import settings from app.application.agentdata import AgentTaskPort as AgentTaskOper class QueryAgentTasksInput(BaseModel): """查询 Agent 自主定时任务的输入参数。""" task_id: Optional[int] = Field( None, ge=1, description="Optional task ID. Omit it to list tasks owned by the current user.", ) enabled: Optional[bool] = Field( None, description="Optional enabled-state filter used when listing tasks.", ) class QueryAgentTasksTool(MoviePilotTool): """查询当前用户创建的 Agent 自主定时任务。""" name: str = "query_agent_tasks" tags: list[str] = [ToolTag.Read, ToolTag.AgentTask, ToolTag.Admin] description: str = ( "Query persistent autonomous agent tasks owned by the current user, including " "reminders, monitoring tasks, and recurring agent work. Returns the integer " "task_id, instructions, trigger, enabled state, next run time, and latest result. " "Do not use this for MoviePilot system, plugin, or workflow scheduler services." ) args_schema: Type[BaseModel] = QueryAgentTasksInput require_admin: bool = True def get_tool_message(self, **kwargs: object) -> Optional[str]: """生成查询定时任务的提示消息。""" task_id = kwargs.get("task_id") return f"查询自主定时任务:{task_id}" if task_id else "查询自主定时任务" def _query_tasks( self, task_id: Optional[int], enabled: Optional[bool], ) -> list[dict]: """读取当前用户的任务及运行时下一次触发时间。""" from app.application.scheduling import get_agent_task_next_run oper = AgentTaskOper() if task_id: task = oper.get(task_id=task_id, user_id=str(self._user_id)) tasks = [task] if task else [] else: tasks = oper.list(user_id=str(self._user_id), enabled=enabled) result = [] for task in tasks: data = oper.to_dict( task, next_run_at=get_agent_task_next_run(task.id), timezone=settings.TZ, ) if task_id: data["recent_runs"] = [ oper.run_to_dict(run) for run in oper.list_runs( task_id=task.id, user_id=str(self._user_id), limit=10, ) ] result.append(data) return result async def run( self, task_id: Optional[int] = None, enabled: Optional[bool] = None, **kwargs: object, ) -> str: """查询 Agent 自主定时任务。""" payload = QueryAgentTasksInput(task_id=task_id, enabled=enabled) tasks = await self.run_blocking( "db", self._query_tasks, payload.task_id, payload.enabled, ) return json.dumps( {"total": len(tasks), "tasks": tasks}, ensure_ascii=False, indent=2, )