73 lines
2.6 KiB
Python
73 lines
2.6 KiB
Python
"""执行器健康状态聚合接口。"""
|
|
from __future__ import annotations
|
|
|
|
import shutil
|
|
import sys
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from sqlalchemy import func, select
|
|
|
|
from app.core.config import settings
|
|
from app.core.deps import DbDep, require_perm
|
|
from app.core.exceptions import ok
|
|
from app.models import LLMProvider, LLMUsage, Skill, Task
|
|
from app.services import lobster_config_service
|
|
|
|
router = APIRouter(prefix="/executors", tags=["executor"])
|
|
|
|
|
|
@router.get("/status", dependencies=[Depends(require_perm("system:executor:view"))])
|
|
async def executor_status(db: DbDep) -> dict:
|
|
lobster_eff = await lobster_config_service.load_effective(db)
|
|
lobster_tasks = (await db.execute(
|
|
select(func.count()).select_from(Task).where(Task.executor_type == "LOBSTER")
|
|
)).scalar() or 0
|
|
script_tasks = (await db.execute(
|
|
select(func.count()).select_from(Task).where(Task.executor_type == "SCRIPT")
|
|
)).scalar() or 0
|
|
|
|
providers_active = (await db.execute(
|
|
select(func.count()).select_from(LLMProvider).where(LLMProvider.status == "ACTIVE")
|
|
)).scalar() or 0
|
|
llm_calls = (await db.execute(select(func.count(LLMUsage.id)))).scalar() or 0
|
|
llm_cost = float((await db.execute(select(func.sum(LLMUsage.cost_usd)))).scalar() or 0)
|
|
|
|
skill_total = (await db.execute(select(func.count(Skill.id)))).scalar() or 0
|
|
|
|
node = "localhost/subprocess"
|
|
python_bin = sys.executable
|
|
node_bin = shutil.which("node")
|
|
bash_bin = shutil.which("bash")
|
|
|
|
return ok({
|
|
"lobster": {
|
|
"configured": not lobster_eff.is_mock,
|
|
"mode": "real" if not lobster_eff.is_mock else "mock",
|
|
"api_base": lobster_eff.api_base or "(未配置)",
|
|
"api_base_source": lobster_eff.api_base_source,
|
|
"api_key_source": lobster_eff.api_key_source,
|
|
"timeout_seconds": lobster_eff.timeout_seconds,
|
|
"poll_interval_seconds": lobster_eff.poll_interval_seconds,
|
|
"callback_configured": bool(lobster_eff.callback_secret),
|
|
"callback_source": lobster_eff.callback_secret_source,
|
|
"task_count": int(lobster_tasks),
|
|
},
|
|
"script": {
|
|
"mode": "subprocess",
|
|
"node": node,
|
|
"python": python_bin,
|
|
"node_bin": node_bin,
|
|
"bash_bin": bash_bin,
|
|
"task_count": int(script_tasks),
|
|
},
|
|
"llm": {
|
|
"providers_active": int(providers_active),
|
|
"total_calls": int(llm_calls),
|
|
"total_cost_usd": round(llm_cost, 6),
|
|
},
|
|
"meta": {
|
|
"skill_total": int(skill_total),
|
|
"app_env": settings.APP_ENV,
|
|
},
|
|
})
|