"""Page routes: GET / (chat), GET /dashboard, dashboard partials.""" from __future__ import annotations import logging from datetime import UTC, datetime from typing import TYPE_CHECKING from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates if TYPE_CHECKING: from ..agent_registry import AgentRegistry from ..config import Config from ..db import Database from ..llm import LLMAdapter from ..scheduler import Scheduler log = logging.getLogger(__name__) router = APIRouter() _registry: AgentRegistry | None = None _config: Config | None = None _llm: LLMAdapter | None = None _db: Database | None = None _scheduler: Scheduler | None = None _templates: Jinja2Templates | None = None def setup(registry, config, llm, templates, db=None, scheduler=None): global _registry, _config, _llm, _templates, _db, _scheduler _registry = registry _config = config _llm = llm _templates = templates _db = db _scheduler = scheduler @router.get("/") async def chat_page(request: Request): agent_names = _registry.list_agents() if _registry else [] agents = [] for name in agent_names: agent = _registry.get(name) display = agent.agent_config.display_name if agent else name agents.append({"name": name, "display_name": display}) default_agent = _registry.default_name if _registry else "default" chat_model = _config.chat_model if _config else "unknown" exec_available = _llm.is_execution_brain_available() if _llm else False clickup_enabled = _config.clickup.enabled if _config else False return _templates.TemplateResponse("chat.html", { "request": request, "agents": agents, "default_agent": default_agent, "chat_model": chat_model, "exec_available": exec_available, "clickup_enabled": clickup_enabled, }) @router.get("/dashboard") async def dashboard_page(request: Request): return _templates.TemplateResponse("dashboard.html", { "request": request, }) @router.get("/dashboard/pipeline") async def dashboard_pipeline(): """Return pipeline panel HTML partial with task data.""" if not _config or not _config.clickup.enabled: return HTMLResponse('
ClickUp not configured
') try: from ..api import get_tasks data = await get_tasks() all_tasks = data.get("tasks", []) except Exception as e: log.error("Pipeline data fetch failed: %s", e) return HTMLResponse(f'Error: {e}
') # Group by work category, then by status pipeline_statuses = [ "to do", "automation underway", "outline review", "internal review", "error", ] categories = {} # category -> {status -> [tasks]} for t in all_tasks: cat = t.get("task_type") or "Other" status = t.get("status", "unknown") # Only show tasks in pipeline-relevant statuses if status not in pipeline_statuses: continue if cat not in categories: categories[cat] = {} categories[cat].setdefault(status, []).append(t) # Build HTML html_parts = [] # Status summary counts total_counts = {} for cat_data in categories.values(): for status, tasks in cat_data.items(): total_counts[status] = total_counts.get(status, 0) + len(tasks) if total_counts: html_parts.append('| Task | Customer | Status | Due | ' '
|---|---|---|---|
| {name_cell} | {customer} | ' f'{status} | ' f'{due_display} |
No active pipeline tasks
') return HTMLResponse('\n'.join(html_parts))