auto-sync: 2026-05-17 00:30:50

This commit is contained in:
cfdaily
2026-05-17 00:30:50 +08:00
parent 4249774d54
commit 39bddb92ee
+126
View File
@@ -0,0 +1,126 @@
"""v2.6 主入口 - FastAPI + Daemon ticker 共享 asyncio event loop"""
import asyncio
import logging
from contextlib import asynccontextmanager
from pathlib import Path
import yaml
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
logger = logging.getLogger("moziplus-v2")
# ---------------------------------------------------------------------------
# 配置加载
# ---------------------------------------------------------------------------
DEFAULT_CONFIG_PATH = Path(__file__).parent.parent / "config" / "default.yaml"
def load_config() -> dict:
"""加载全局默认配置"""
if DEFAULT_CONFIG_PATH.exists():
with open(DEFAULT_CONFIG_PATH) as f:
return yaml.safe_load(f) or {}
return {}
config = load_config()
# ---------------------------------------------------------------------------
# Daemon ticker(占位,F6 实现)
# ---------------------------------------------------------------------------
_ticker_task: asyncio.Task | None = None
async def _run_ticker():
"""Daemon ticker 主循环(占位)"""
tick_interval = config.get("daemon", {}).get("tick_interval", 30)
logger.info("Ticker started (interval=%ss)", tick_interval)
while True:
try:
# F6 会在这里注入真正的 tick 逻辑
await asyncio.sleep(tick_interval)
except asyncio.CancelledError:
logger.info("Ticker cancelled")
return
except Exception:
logger.exception("Tick error")
await asyncio.sleep(tick_interval)
# ---------------------------------------------------------------------------
# FastAPI 生命周期
# ---------------------------------------------------------------------------
@asynccontextmanager
async def lifespan(app: FastAPI):
"""启动 Daemon ticker,关闭时清理"""
global _ticker_task
logger.info("moziplus-v2 starting...")
_ticker_task = asyncio.create_task(_run_ticker())
yield
if _ticker_task:
_ticker_task.cancel()
try:
await _ticker_task
except asyncio.CancelledError:
pass
logger.info("moziplus-v2 stopped")
# ---------------------------------------------------------------------------
# FastAPI app
# ---------------------------------------------------------------------------
app = FastAPI(
title="Sanguo MoziPlus v2",
description="AI Native DevOps Platform - Blackboard Architecture",
version="2.6.0",
lifespan=lifespan,
)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# ---------------------------------------------------------------------------
# 健康端点
# ---------------------------------------------------------------------------
@app.get("/api/daemon/status")
async def daemon_status():
"""Daemon 健康检查"""
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),
},
}
@app.get("/api/projects")
async def list_projects():
"""列出所有项目(占位,F3 实现)"""
return {"projects": []}
# ---------------------------------------------------------------------------
# 静态文件服务(前端 dist/,F18 实现)
# ---------------------------------------------------------------------------
DIST_DIR = Path(__file__).parent / "frontend" / "dist"
if DIST_DIR.exists():
app.mount("/", StaticFiles(directory=str(DIST_DIR), html=True), name="frontend")