From aeab2684804da197dcecb21c5c3ccabe9dd4ec68 Mon Sep 17 00:00:00 2001 From: cfdaily Date: Sun, 17 May 2026 00:46:35 +0800 Subject: [PATCH] auto-sync: 2026-05-17 00:46:35 --- src/api/daemon_routes.py | 27 ++++++++++++++++++ src/api/project_routes.py | 58 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/api/daemon_routes.py create mode 100644 src/api/project_routes.py diff --git a/src/api/daemon_routes.py b/src/api/daemon_routes.py new file mode 100644 index 0000000..6c0d823 --- /dev/null +++ b/src/api/daemon_routes.py @@ -0,0 +1,27 @@ +"""API 路由 — Daemon 控制""" + +from __future__ import annotations + +from fastapi import APIRouter + +router = APIRouter(prefix="/api/daemon", tags=["daemon"]) + + +@router.get("/status") +async def daemon_status(): + from src.main import _ticker_task, config + return { + "status": "running", + "version": "2.6.0", + "ticker_running": _ticker_task is not None and not _ticker_task.done(), + "config": { + "tick_interval": config.get("daemon", {}).get("tick_interval", 30), + "max_global_agents": config.get("daemon", {}).get("max_global_agents", 5), + }, + } + + +@router.post("/tick") +async def manual_tick(): + """触发手动 tick(占位,F6 实现)""" + return {"ok": True, "message": "Manual tick triggered (placeholder)"} diff --git a/src/api/project_routes.py b/src/api/project_routes.py new file mode 100644 index 0000000..0f38255 --- /dev/null +++ b/src/api/project_routes.py @@ -0,0 +1,58 @@ +"""API 路由 — 项目管理""" + +from __future__ import annotations + +from pathlib import Path +from typing import Any, Dict, List, Optional + +from fastapi import APIRouter, HTTPException + +from src.blackboard.registry import ProjectRegistry + +router = APIRouter(prefix="/api/projects", tags=["projects"]) + + +def _registry() -> ProjectRegistry: + import os + root = Path(os.environ.get("BLACKBOARD_ROOT", + str(Path.home() / ".sanguo_projects" / "sanguo_moziplus_v2" / "projects"))) + return ProjectRegistry(root) + + +@router.get("") +async def list_projects(): + reg = _registry() + projects = reg.list_projects() + return {"projects": {pid: info for pid, info in projects.items() + if info.get("status") != "archived"}} + + +@router.post("") +async def create_project(body: Dict[str, Any]): + reg = _registry() + try: + info = reg.create_project( + body["id"], body["name"], + agents=body.get("agents", []), + description=body.get("description", ""), + ) + return {"ok": True, "project_id": body["id"]} + except ValueError as e: + raise HTTPException(409, str(e)) + + +@router.get("/{project_id}") +async def get_project(project_id: str): + reg = _registry() + info = reg.get_project(project_id) + if not info: + raise HTTPException(404, f"Project not found: {project_id}") + return info + + +@router.post("/{project_id}/archive") +async def archive_project(project_id: str): + reg = _registry() + if not reg.archive_project(project_id): + raise HTTPException(404, f"Project not found: {project_id}") + return {"ok": True}