""" AI Assistant 可执行操作注册表 """ import json from datetime import datetime, timezone, timedelta from typing import Dict, Any, List, Optional from ..database import SessionLocal from ..models import Topic, ContentTask, TaskLog, SystemConfig, TopicField, Case from ..core.scheduler import scheduler as bg_scheduler # -------------------- 工具函数 -------------------- def list_topics( page: int = 1, page_size: int = 20, status: Optional[str] = None, field: Optional[str] = None, org_id: Optional[str] = None, ) -> Dict[str, Any]: """获取选题列表,支持分页和筛选""" db = SessionLocal() try: query = db.query(Topic) if org_id: query = query.filter(Topic.org_id == org_id) if status: query = query.filter(Topic.status == status) if field: query = query.filter(Topic.field_name == field) total = query.count() items = query.order_by(Topic.priority.desc(), Topic.created_at.desc()) \ .offset((page - 1) * page_size) \ .limit(page_size) \ .all() result_items = [] for t in items: result_items.append({ "id": t.id, "title": t.title, "field": t.field_name, "status": t.status, "priority": t.priority, "priority_score": t.priority_score, "created_at": t.created_at.isoformat() if t.created_at else None }) return { "total": total, "page": page, "page_size": page_size, "items": result_items } finally: db.close() def get_topic(topic_id: str, org_id: Optional[str] = None) -> Dict[str, Any]: """获取单个选题详情""" db = SessionLocal() try: query = db.query(Topic).filter(Topic.id == topic_id) if org_id: query = query.filter(Topic.org_id == org_id) t = query.first() if not t: return {"error": f"选题 {topic_id} 不存在"} return { "id": t.id, "title": t.title, "field": t.field_name, "status": t.status, "priority": t.priority, "priority_score": t.priority_score, "core_concept": t.core_concept, "audience_pain": t.audience_pain, "unique_angle": t.unique_angle, "cases": t.cases or [], "tags": t.tags or [], "platform_urls": t.platform_urls or {}, "created_at": t.created_at.isoformat() if t.created_at else None } finally: db.close() def get_recent_task_logs(limit: int = 10) -> List[Dict[str, Any]]: """获取最近的任务执行日志""" db = SessionLocal() try: logs = db.query(TaskLog).order_by(TaskLog.started_at.desc()).limit(limit).all() return [{ "id": l.id, "module_id": l.module_id, "status": l.status, "message": l.message, "started_at": l.started_at.isoformat() if l.started_at else None, "finished_at": l.finished_at.isoformat() if l.finished_at else None, "triggered_by": l.triggered_by } for l in logs] finally: db.close() def get_system_stats() -> Dict[str, Any]: """获取系统概览统计数据""" db = SessionLocal() try: total_topics = db.query(Topic).count() pending = db.query(Topic).filter(Topic.status == "pending").count() review = db.query(Topic).filter(Topic.status == "review").count() draft = db.query(Topic).filter(Topic.status == "draft").count() ready = db.query(Topic).filter(Topic.status == "ready").count() published = db.query(Topic).filter(Topic.status == "published").count() total_cases = db.query(Case).count() week_ago = datetime.now(timezone.utc).replace(hour=0, minute=0, second=0, microsecond=0) - timedelta(days=7) new_this_week = db.query(Topic).filter(Topic.created_at >= week_ago).count() return { "topics": { "total": total_topics, "pending": pending, "review": review, "draft": draft, "ready": ready, "published": published, "new_this_week": new_this_week }, "cases": total_cases, "date": datetime.now(timezone.utc).isoformat() } finally: db.close() def get_task_status(module_id: Optional[str] = None) -> List[Dict[str, Any]]: """查询任务日志(如 collector、generator、optimizer 等)""" db = SessionLocal() try: query = db.query(TaskLog) if module_id: query = query.filter(TaskLog.module_id == module_id) logs = query.order_by(TaskLog.started_at.desc()).limit(10).all() return [{ "id": l.id, "module_id": l.module_id, "status": l.status, "message": l.message, "started_at": l.started_at.isoformat() if l.started_at else None, "finished_at": l.finished_at.isoformat() if l.finished_at else None, "triggered_by": l.triggered_by } for l in logs] finally: db.close() def trigger_task(module_id: str) -> Dict[str, Any]: """手动触发定时任务(如 collector、generator、optimizer、metrics_sync 等)""" # 只允许触发特定任务 allowed = ["scheduled_collect", "scheduled_generate", "scheduled_optimize", "scheduled_optimize_sources", "scheduled_metrics_sync", "scheduled_trends"] if module_id not in allowed: return {"error": f"不允许手动触发该任务: {module_id}"} job_id = module_id if module_id.startswith("scheduled_") else f"scheduled_{module_id}" # 检查任务是否存在 job = bg_scheduler.get_job(job_id) if not job: return {"error": f"任务不存在: {job_id}"} try: # 如果任务正在运行,返回提示 # APScheduler 的 run_job 会立即执行 bg_scheduler.run_job(job_id) return {"success": True, "message": f"任务 {job_id} 已触发执行"} except Exception as e: return {"error": str(e)} def search_web(query: str, max_results: int = 5) -> List[Dict[str, Any]]: """联网搜索(通过本项目的 search_utils)""" try: from ...scripts.search_utils import search as web_search results = web_search(query, max_results) return {"success": True, "results": results, "count": len(results)} except Exception as e: return {"error": str(e)} def list_system_configs() -> List[Dict[str, Any]]: """列出系统配置项""" db = SessionLocal() try: configs = db.query(SystemConfig).all() return [{"key": c.key, "value": c.value, "description": c.description} for c in configs] finally: db.close() # Action registry ACTION_REGISTRY = { "list_topics": { "func": list_topics, "description": "获取选题列表,支持分页(page, page_size)和筛选(status, field, org_id)", "params_schema": { "page": {"type": "integer", "default": 1, "desc": "页码"}, "page_size": {"type": "integer", "default": 20, "desc": "每页条数"}, "status": {"type": "string", "enum": ["pending", "review", "draft", "ready", "published"], "desc": "按状态筛选"}, "field": {"type": "string", "desc": "按领域筛选"}, "org_id": {"type": "string", "desc": "按组织筛选"} } }, "get_topic": { "func": get_topic, "description": "获取单个选题详情", "params_schema": { "topic_id": {"type": "string", "desc": "选题ID,如 A01 或 LIVING-001-26"}, "org_id": {"type": "string", "desc": "按组织筛选(可选)"} } }, "get_recent_task_logs": { "func": get_recent_task_logs, "description": "获取最近的任务执行日志", "params_schema": { "limit": {"type": "integer", "default": 10, "desc": "返回条数"} } }, "get_system_stats": { "func": get_system_stats, "description": "获取系统概览统计(选题总数、各状态数量、案例数等)", "params_schema": {} }, "get_task_status": { "func": get_task_status, "description": "查询任务日志,可按模块ID筛选", "params_schema": { "module_id": {"type": "string", "desc": "可选:筛选特定模块ID(如 scheduled_collect)"} } }, "trigger_task": { "func": trigger_task, "description": "手动触发定时任务(采集、生成、优化、指标同步等)", "params_schema": { "module_id": {"type": "string", "desc": "任务模块ID:scheduled_collect/scheduled_generate/scheduled_optimize/scheduled_optimize_sources/scheduled_metrics_sync/scheduled_trends"} } }, "search_web": { "func": search_web, "description": "执行网络搜索,返回结构化结果", "params_schema": { "query": {"type": "string", "desc": "搜索关键词"}, "max_results": {"type": "integer", "default": 5, "desc": "返回结果数量"} } }, "list_system_configs": { "func": list_system_configs, "description": "列出所有系统配置项(key/value)", "params_schema": {} } }