Skip to content

Commit 00386c6

Browse files
Copilotgarland3
andauthored
Replace Google Fonts CDN with self-hosted Inter font files (#47)
* Initial plan * Replace Google Fonts CDN with self-hosted Inter font files Co-authored-by: garland3 <[email protected]> * feat: add system status endpoint and enhance LogViewer component * refactor: clean up backend code by removing dead code and disabling file processing - Remove large block of commented-out system status and MCP health endpoints from admin_routes.py - Disable file processing in websocket_update_callback for canvas_files and files_update types in main.py, replacing with pass statements This commit streamlines the codebase by eliminating unused commented code and temporarily disabling non-essential file update handling in websocket callbacks. * refactor(websocket): simplify intermediate update handling by removing commented logging - Consolidated handling for 'canvas_files' and 'files_update' types - Removed disabled logging code to reduce noise and improve readability - Preserves functionality while cleaning up the websocket callback logic --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: garland3 <[email protected]> Co-authored-by: Anthony <[email protected]>
1 parent 92c6e55 commit 00386c6

File tree

10 files changed

+204
-214
lines changed

10 files changed

+204
-214
lines changed

backend/main.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,10 @@ async def websocket_update_callback(websocket: WebSocket, message: dict):
4949
mtype = message.get("type")
5050
if mtype == "intermediate_update":
5151
utype = message.get("update_type") or message.get("data", {}).get("update_type")
52-
if utype == "canvas_files":
53-
files = (message.get("data") or {}).get("files") or []
54-
# logger.info(
55-
# "WS SEND: intermediate_update canvas_files count=%d files=%s display=%s",
56-
# len(files),
57-
# [f.get("filename") for f in files if isinstance(f, dict)],
58-
# (message.get("data") or {}).get("display"),
59-
# )
60-
elif utype == "files_update":
61-
files = (message.get("data") or {}).get("files") or []
62-
# logger.info(
63-
# "WS SEND: intermediate_update files_update total=%d",
64-
# len(files),
65-
# )
66-
# else:
67-
# logger.info("WS SEND: intermediate_update update_type=%s", utype)
52+
# Handle specific update types (canvas_files, files_update)
53+
# Logging disabled for these message types - see git history if needed
54+
if utype in ("canvas_files", "files_update"):
55+
pass
6856
elif mtype == "canvas_content":
6957
content = message.get("content")
7058
clen = len(content) if isinstance(content, str) else "obj"
@@ -142,7 +130,8 @@ async def lifespan(app: FastAPI):
142130
app.include_router(files_router)
143131

144132
# Serve frontend build (Vite)
145-
static_dir = Path(__file__).parent.parent / "frontend" / "dist"
133+
project_root = Path(__file__).resolve().parents[1]
134+
static_dir = project_root / "frontend" / "dist"
146135
if static_dir.exists():
147136
# Serve the SPA entry
148137
@app.get("/")
@@ -154,6 +143,16 @@ async def read_root():
154143
if assets_dir.exists():
155144
app.mount("/assets", StaticFiles(directory=assets_dir), name="assets")
156145

146+
# Serve webfonts from Vite build (placed via frontend/public/fonts)
147+
fonts_dir = static_dir / "fonts"
148+
if fonts_dir.exists():
149+
app.mount("/fonts", StaticFiles(directory=fonts_dir), name="fonts")
150+
else:
151+
# Fallback to unbuilt public fonts if dist/fonts is missing
152+
public_fonts = project_root / "frontend" / "public" / "fonts"
153+
if public_fonts.exists():
154+
app.mount("/fonts", StaticFiles(directory=public_fonts), name="fonts")
155+
157156
# Common top-level static files in the Vite build
158157
@app.get("/favicon.ico")
159158
async def favicon():

backend/routes/admin_routes.py

Lines changed: 47 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -598,140 +598,53 @@ async def download_logs(admin_user: str = Depends(require_admin)):
598598
raise HTTPException(status_code=500, detail="Error preparing log download")
599599

600600

601-
# # --- System Status ---
601+
# --- System Status (minimal) ---
602602

603-
# @admin_router.get("/system-status")
604-
# async def get_system_status(admin_user: str = Depends(require_admin)):
605-
# """Get overall system status including MCP servers and LLM health."""
606-
# try:
607-
# status_info = []
608-
609-
# # Check if configfilesadmin exists and has files
610-
# admin_config_dir = Path("configfilesadmin")
611-
# config_status = "healthy" if admin_config_dir.exists() and any(admin_config_dir.iterdir()) else "warning"
612-
# status_info.append(SystemStatus(
613-
# component="Configuration",
614-
# status=config_status,
615-
# details={
616-
# "admin_config_dir": str(admin_config_dir),
617-
# "files_count": len(list(admin_config_dir.glob("*"))) if admin_config_dir.exists() else 0
618-
# }
619-
# ))
620-
621-
# # Check log file
622-
# from otel_config import get_otel_config
623-
# otel_cfg = get_otel_config()
624-
# log_file = otel_cfg.get_log_file_path() if otel_cfg else Path("logs/app.jsonl")
625-
# log_status = "healthy" if log_file.exists() else "warning"
626-
# status_info.append(SystemStatus(
627-
# component="Logging",
628-
# status=log_status,
629-
# details={
630-
# "log_file": str(log_file),
631-
# "exists": log_file.exists(),
632-
# "size_bytes": log_file.stat().st_size if log_file.exists() else 0
633-
# }
634-
# ))
635-
636-
# # Check MCP server health
637-
# mcp_health = get_mcp_health_status()
638-
# mcp_status = mcp_health.get("overall_status", "unknown")
639-
# status_info.append(SystemStatus(
640-
# component="MCP Servers",
641-
# status=mcp_status,
642-
# details={
643-
# "healthy_count": mcp_health.get("healthy_count", 0),
644-
# "total_count": mcp_health.get("total_count", 0),
645-
# "last_check": mcp_health.get("last_check"),
646-
# "check_interval": mcp_health.get("check_interval", 300)
647-
# }
648-
# ))
649-
650-
# return {
651-
# "overall_status": "healthy" if all(s.status == "healthy" for s in status_info) else "warning",
652-
# "components": [s.model_dump() for s in status_info],
653-
# "checked_by": admin_user,
654-
# "timestamp": log_file.stat().st_mtime if log_file.exists() else None
655-
# }
656-
# except Exception as e:
657-
# logger.error(f"Error getting system status: {e}")
658-
# raise HTTPException(status_code=500, detail=str(e))
659-
660-
661-
# # --- Health Check Trigger ---
662-
663-
# @admin_router.get("/mcp-health")
664-
# async def get_mcp_health(admin_user: str = Depends(require_admin)):
665-
# """Get detailed MCP server health information."""
666-
# try:
667-
# health_summary = get_mcp_health_status()
668-
# return {
669-
# "health_summary": health_summary,
670-
# "checked_by": admin_user
671-
# }
672-
# except Exception as e:
673-
# logger.error(f"Error getting MCP health: {e}")
674-
# raise HTTPException(status_code=500, detail=str(e))
675-
676-
677-
# @admin_router.post("/trigger-health-check")
678-
# async def trigger_health_check(admin_user: str = Depends(require_admin)):
679-
# """Manually trigger MCP server health checks."""
680-
# try:
681-
# # Try to get the MCP manager from main application state
682-
# mcp_manager = None
683-
# try:
684-
# from main import mcp_manager as main_mcp_manager
685-
# mcp_manager = main_mcp_manager
686-
# except ImportError:
687-
# # In test environment, mcp_manager might not be available
688-
# logger.warning("MCP manager not available for health check")
689-
690-
# # Trigger health check
691-
# health_results = await trigger_mcp_health_check(mcp_manager)
692-
693-
# # Get summary
694-
# health_summary = get_mcp_health_status()
695-
696-
# logger.info(f"Health check triggered by {admin_user}")
697-
# return {
698-
# "message": "MCP server health check completed",
699-
# "triggered_by": admin_user,
700-
# "summary": health_summary,
701-
# "details": health_results
702-
# }
703-
# except Exception as e:
704-
# logger.error(f"Error triggering health check: {e}")
705-
# raise HTTPException(status_code=500, detail=f"Error triggering health check: {str(e)}")
603+
@admin_router.get("/system-status")
604+
async def get_system_status(admin_user: str = Depends(require_admin)):
605+
"""Minimal system status endpoint for the Admin UI.
706606
607+
Returns basic configuration and logging status; avoids heavy checks.
608+
"""
609+
try:
610+
# Configuration status: overrides directory and file count
611+
overrides_root = Path(os.getenv("APP_CONFIG_OVERRIDES", "config/overrides"))
612+
overrides_root.mkdir(parents=True, exist_ok=True)
613+
config_files = list(overrides_root.glob("*"))
614+
config_status = "healthy" if config_files else "warning"
615+
616+
# Logging status
617+
log_dir = _log_base_dir()
618+
log_file = log_dir / "app.jsonl"
619+
log_exists = log_file.exists()
620+
logging_status = "healthy" if log_exists else "warning"
621+
622+
components = [
623+
{
624+
"component": "Configuration",
625+
"status": config_status,
626+
"details": {
627+
"overrides_dir": str(overrides_root),
628+
"files_count": len(config_files),
629+
},
630+
},
631+
{
632+
"component": "Logging",
633+
"status": logging_status,
634+
"details": {
635+
"log_file": str(log_file),
636+
"exists": log_exists,
637+
"size_bytes": log_file.stat().st_size if log_exists else 0,
638+
},
639+
},
640+
]
707641

708-
# @admin_router.post("/reload-config")
709-
# async def reload_configuration(admin_user: str = Depends(require_admin)):
710-
# """Reload configuration from configfilesadmin files."""
711-
# try:
712-
# # Reload configuration from files
713-
# config_manager.reload_configs()
714-
715-
# # Validate the reloaded configurations
716-
# validation_status = config_manager.validate_config()
717-
718-
# # Get the updated configurations for verification
719-
# llm_models = list(config_manager.llm_config.models.keys())
720-
# mcp_servers = list(config_manager.mcp_config.servers.keys())
721-
722-
# logger.info(f"Configuration reloaded by {admin_user}")
723-
# logger.info(f"Reloaded LLM models: {llm_models}")
724-
# logger.info(f"Reloaded MCP servers: {mcp_servers}")
725-
726-
# return {
727-
# "message": "Configuration reloaded successfully",
728-
# "reloaded_by": admin_user,
729-
# "validation_status": validation_status,
730-
# "llm_models_count": len(llm_models),
731-
# "mcp_servers_count": len(mcp_servers),
732-
# "llm_models": llm_models,
733-
# "mcp_servers": mcp_servers
734-
# }
735-
# except Exception as e:
736-
# logger.error(f"Error reloading config: {e}")
737-
# raise HTTPException(status_code=500, detail=f"Error reloading configuration: {str(e)}")
642+
overall = "healthy" if all(c["status"] == "healthy" for c in components) else "warning"
643+
return {
644+
"overall_status": overall,
645+
"components": components,
646+
"checked_by": admin_user,
647+
}
648+
except Exception as e: # noqa: BLE001
649+
logger.error(f"Error getting system status: {e}")
650+
raise HTTPException(status_code=500, detail=str(e))

backend/tests/test_security_admin_routes.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,46 @@ def test_admin_routes_require_admin(monkeypatch):
1717
assert r2.status_code == 200
1818
data = r2.json()
1919
assert data.get("available_endpoints") is not None
20+
21+
22+
def test_system_status_endpoint():
23+
"""Test the system status endpoint returns expected data structure."""
24+
client = TestClient(app)
25+
26+
# Test with admin user
27+
r = client.get("/admin/system-status", headers={"X-User-Email": "[email protected]"})
28+
assert r.status_code == 200
29+
30+
data = r.json()
31+
32+
# Check response structure
33+
assert "overall_status" in data
34+
assert "components" in data
35+
assert "checked_by" in data
36+
37+
# Overall status should be "healthy" or "warning"
38+
assert data["overall_status"] in ("healthy", "warning")
39+
40+
# Components should be a list
41+
assert isinstance(data["components"], list)
42+
43+
# Check that expected components are present
44+
component_names = [c["component"] for c in data["components"]]
45+
assert "Configuration" in component_names
46+
assert "Logging" in component_names
47+
48+
# Each component should have required fields
49+
for component in data["components"]:
50+
assert "component" in component
51+
assert "status" in component
52+
assert "details" in component
53+
assert component["status"] in ("healthy", "warning", "error")
54+
55+
56+
def test_system_status_requires_admin():
57+
"""Test that system status endpoint requires admin access."""
58+
client = TestClient(app)
59+
60+
# Non-admin user should be denied
61+
r = client.get("/admin/system-status", headers={"X-User-Email": "[email protected]"})
62+
assert r.status_code in (302, 403)
108 KB
Binary file not shown.
109 KB
Binary file not shown.
106 KB
Binary file not shown.
109 KB
Binary file not shown.

0 commit comments

Comments
 (0)