diff --git a/backend/app/services/builtin_tools.py b/backend/app/services/builtin_tools.py index dc44f85..eae66cd 100644 --- a/backend/app/services/builtin_tools.py +++ b/backend/app/services/builtin_tools.py @@ -1848,12 +1848,20 @@ async def schedule_list_tool(agent_id: str) -> str: return json.dumps({"error": f"查询定时任务失败: {e}"}, ensure_ascii=False) -async def schedule_delete_tool(schedule_id: str) -> str: +async def schedule_delete_tool( + schedule_id: str = "", + agent_id: str = "", +) -> str: """ 删除指定的定时任务。 + 支持三种删除方式: + 1. 按 schedule_id 精确删除 + 2. 按 agent_id 删除该 Agent 下所有定时任务(批量清理) + Args: - schedule_id: 定时任务 ID + schedule_id: 定时任务 ID(精确删除时使用) + agent_id: Agent ID(批量删除该 Agent 的所有任务时使用,或用于校验 schedule_id 所属权) Returns: 删除结果 @@ -1862,22 +1870,65 @@ async def schedule_delete_tool(schedule_id: str) -> str: from app.core.database import SessionLocal from app.models.agent_schedule import AgentSchedule + if not schedule_id and not agent_id: + return json.dumps({ + "error": "missing_params", + "message": "请提供 schedule_id(删除单个)或 agent_id(批量删除该 Agent 的所有定时任务)", + }, ensure_ascii=False) + db = SessionLocal() try: - schedule = db.query(AgentSchedule).filter(AgentSchedule.id == schedule_id).first() - if not schedule: - return json.dumps({"error": f"定时任务不存在: {schedule_id}"}, ensure_ascii=False) + if schedule_id: + # 按 ID 精确删除 + schedule = db.query(AgentSchedule).filter(AgentSchedule.id == schedule_id).first() + if not schedule: + db.close() + return json.dumps({"error": f"定时任务不存在: {schedule_id}"}, ensure_ascii=False) - name = schedule.name - db.delete(schedule) - db.commit() + # 所有权校验:如果提供了 agent_id,确保该 schedule 属于此 Agent + if agent_id and schedule.agent_id != agent_id: + db.close() + return json.dumps({ + "error": "permission_denied", + "message": f"定时任务「{schedule.name}」不属于 Agent {agent_id}", + }, ensure_ascii=False) - return json.dumps({ - "success": True, - "message": f"定时任务「{name}」已删除", - }, ensure_ascii=False) + name = schedule.name + db.delete(schedule) + db.commit() + db.close() + return json.dumps({ + "success": True, + "message": f"定时任务「{name}」已删除", + }, ensure_ascii=False) + + elif agent_id: + # 批量删除该 Agent 的所有定时任务 + schedules = db.query(AgentSchedule).filter(AgentSchedule.agent_id == agent_id).all() + if not schedules: + db.close() + return json.dumps({ + "success": True, + "message": f"Agent {agent_id} 没有定时任务需要删除", + "deleted_count": 0, + }, ensure_ascii=False) + + names = [s.name for s in schedules] + count = len(schedules) + for s in schedules: + db.delete(s) + db.commit() + db.close() + return json.dumps({ + "success": True, + "message": f"已删除 {count} 个定时任务:{', '.join(names)}", + "deleted_count": count, + }, ensure_ascii=False) finally: - db.close() + try: + db.close() + except Exception: + pass except Exception as e: logger.error(f"schedule_delete 工具执行失败: {e}", exc_info=True) return json.dumps({"error": f"删除定时任务失败: {e}"}, ensure_ascii=False) @@ -2131,16 +2182,25 @@ SCHEDULE_DELETE_SCHEMA = { "type": "function", "function": { "name": "schedule_delete", - "description": "删除指定的定时任务。", + "description": ( + "删除定时任务。支持两种方式:" + "1) 提供 schedule_id 精确删除单个任务;" + "2) 提供 agent_id 批量删除该 Agent 的所有任务。" + "建议同时提供 agent_id 以校验所有权。" + ), "parameters": { "type": "object", "properties": { "schedule_id": { "type": "string", - "description": "定时任务 ID(可从 schedule_list 查询获得)", + "description": "定时任务 ID(精确删除单个任务时使用,可从 schedule_list 查询获得)", + }, + "agent_id": { + "type": "string", + "description": "Agent ID(用于校验 schedule_id 的所属权,或批量删除该 Agent 的所有任务)", }, }, - "required": ["schedule_id"], + "required": [], }, }, } diff --git a/backend/app/services/feishu_ws_handler.py b/backend/app/services/feishu_ws_handler.py index c2f443e..3cecc1e 100644 --- a/backend/app/services/feishu_ws_handler.py +++ b/backend/app/services/feishu_ws_handler.py @@ -176,7 +176,11 @@ async def _handle_message_async(data): config = AgentConfig( name=agent.name or "agent", - system_prompt=system_prompt, + system_prompt=system_prompt + ( + f"\n\n## 系统信息\n" + f"你的 Agent ID 是: {agent.id}\n" + f"在调用 schedule_list、schedule_delete 等工具时,使用此 ID 作为 agent_id 参数。" + ), llm=AgentLLMConfig( model=model, provider=provider, diff --git a/backend/app/services/lingxi_ws_handler.py b/backend/app/services/lingxi_ws_handler.py index 2ef83bd..f81561e 100644 --- a/backend/app/services/lingxi_ws_handler.py +++ b/backend/app/services/lingxi_ws_handler.py @@ -166,7 +166,11 @@ async def _handle_message_async(data): config = AgentConfig( name=agent.name or "灵犀", - system_prompt=system_prompt, + system_prompt=system_prompt + ( + f"\n\n## 系统信息\n" + f"你的 Agent ID 是: {agent.id}\n" + f"在调用 schedule_list、schedule_delete 等工具时,使用此 ID 作为 agent_id 参数。" + ), llm=AgentLLMConfig( model=model, provider=provider, temperature=temperature, max_iterations=max_iterations, diff --git a/backend/app/services/orange_ws_handler.py b/backend/app/services/orange_ws_handler.py index 2752248..f569de0 100644 --- a/backend/app/services/orange_ws_handler.py +++ b/backend/app/services/orange_ws_handler.py @@ -180,7 +180,11 @@ async def _handle_message_async(data): config = AgentConfig( name=agent.name or "橙子助手", - system_prompt=system_prompt, + system_prompt=system_prompt + ( + f"\n\n## 系统信息\n" + f"你的 Agent ID 是: {agent.id}\n" + f"在调用 schedule_list、schedule_delete 等工具时,使用此 ID 作为 agent_id 参数。" + ), llm=AgentLLMConfig( model=model, provider=provider, diff --git a/backend/app/services/suyao_ws_handler.py b/backend/app/services/suyao_ws_handler.py index 06de64f..6757b91 100644 --- a/backend/app/services/suyao_ws_handler.py +++ b/backend/app/services/suyao_ws_handler.py @@ -180,7 +180,11 @@ async def _handle_message_async(data): config = AgentConfig( name=agent.name or "苏瑶", - system_prompt=system_prompt, + system_prompt=system_prompt + ( + f"\n\n## 系统信息\n" + f"你的 Agent ID 是: {agent.id}\n" + f"在调用 schedule_list、schedule_delete 等工具时,使用此 ID 作为 agent_id 参数。" + ), llm=AgentLLMConfig( model=model, provider=provider, diff --git a/backend/app/services/tiantian_ws_handler.py b/backend/app/services/tiantian_ws_handler.py index 3089103..776c58b 100644 --- a/backend/app/services/tiantian_ws_handler.py +++ b/backend/app/services/tiantian_ws_handler.py @@ -164,7 +164,11 @@ async def _handle_message_async(data): config = AgentConfig( name=agent.name or "甜甜", - system_prompt=system_prompt, + system_prompt=system_prompt + ( + f"\n\n## 系统信息\n" + f"你的 Agent ID 是: {agent.id}\n" + f"在调用 schedule_list、schedule_delete 等工具时,使用此 ID 作为 agent_id 参数。" + ), llm=AgentLLMConfig( model=model, provider=provider, temperature=temperature, max_iterations=max_iterations,