"""Admin page data for skill-view timing. A row is written only after the sandbox tool call returns, and it keeps that call's command plus any skill name the call actually invoked. Rows older than one day are dropped. """ from __future__ import annotations from typing import Literal from fastapi import APIRouter, Query, Request from pydantic import BaseModel, Field from app.gateway.routers.admin_users import _require_admin from deerflow.config.runtime_performance_config import get_runtime_performance_config from deerflow.sandbox.skill_view import query_skill_view_events router = APIRouter(prefix="/api/admin/skill-view-diagnostics", tags=["admin-skill-view"]) class SkillViewCheck(BaseModel): id: str title: str result: str level: str look_at: str cause: str command: str = "" skill_names: list[str] = Field(default_factory=list) class SkillViewExplanation(BaseModel): level: str headline: str look_at: str cause: str class SkillViewEvent(BaseModel): at: str status: str total_ms: float lock_wait_ms: float refresh_ms: float source_entries: int target_entries: int enabled_count: int path_count: int tool: str = "" command: str = "" skill_names: list[str] = Field(default_factory=list) tool_ms: float = 0 explanation: SkillViewExplanation class SkillViewDiagnosticsResponse(BaseModel): cache_enabled: bool reuse_enabled: bool level: str conclusion: str checks: list[SkillViewCheck] = Field(default_factory=list) events: list[SkillViewEvent] = Field(default_factory=list) total: int = 0 page: int = 1 page_size: int = 20 sort: str = "time" order: str = "desc" @router.get("", response_model=SkillViewDiagnosticsResponse) async def get_skill_view_diagnostics( request: Request, page: int = Query(default=1, ge=1), page_size: int = Query(default=20, ge=1, le=100), sort: Literal["time", "duration", "check"] = Query(default="time"), order: Literal["asc", "desc"] = Query(default="desc"), ) -> SkillViewDiagnosticsResponse: await _require_admin(request) flags = get_runtime_performance_config() report = query_skill_view_events( page=page, page_size=page_size, sort=sort, order=order, cache_enabled=flags.skill_view_cache_enabled, reuse_enabled=flags.skill_view_reuse_enabled, ) return SkillViewDiagnosticsResponse( cache_enabled=flags.skill_view_cache_enabled, reuse_enabled=flags.skill_view_reuse_enabled, level=report["level"], conclusion=report["conclusion"], checks=report["checks"], events=report["events"], total=report["total"], page=report["page"], page_size=report["page_size"], sort=report["sort"], order=report["order"], )