"""Router main module - FastAPI app factory. Creates the FastAPI application with: - Feishu WebSocket client - Node WebSocket endpoint - Health check endpoints """ from __future__ import annotations import logging from typing import Optional from fastapi import FastAPI, WebSocket from fastapi.middleware.cors import CORSMiddleware from bot.handler import start_websocket_client from router.nodes import NodeRegistry, get_node_registry from router.ws import ws_node_endpoint logger = logging.getLogger(__name__) def create_app(router_secret: Optional[str] = None) -> FastAPI: """Create the FastAPI application. Args: router_secret: Secret for authenticating host client connections """ app = FastAPI(title="PhoneWork Router", version="3.0.0") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) registry = get_node_registry() if router_secret: registry._secret = router_secret @app.get("/health") async def health(): nodes = registry.list_nodes() online_nodes = [n for n in nodes if n["status"] == "online"] return { "status": "ok", "nodes": nodes, "online_nodes": len(online_nodes), "total_nodes": len(nodes), "pending_requests": 0, } @app.get("/nodes") async def list_nodes(): return registry.list_nodes() @app.websocket("/ws/node") async def ws_node(websocket: WebSocket): await ws_node_endpoint(websocket) @app.on_event("startup") async def startup(): import asyncio loop = asyncio.get_event_loop() start_websocket_client(loop) logger.info("Router started") @app.on_event("shutdown") async def shutdown(): logger.info("Router shut down") return app