From d7e2524073a08b6cd11578d9fe094bc6f45144a6 Mon Sep 17 00:00:00 2001
From: sambella
Date: Fri, 16 Jan 2026 22:32:34 +0530
Subject: [PATCH 1/3] Add system diagnostics health endpoint and UI
---
backend/app/controller/health_controller.py | 90 ++++++++++++++++++++-
src/pages/Diagnostics.tsx | 57 +++++++++++++
src/routers/index.tsx | 28 +++++--
3 files changed, 165 insertions(+), 10 deletions(-)
create mode 100644 src/pages/Diagnostics.tsx
diff --git a/backend/app/controller/health_controller.py b/backend/app/controller/health_controller.py
index 87ea5e2d0..40083e8b8 100644
--- a/backend/app/controller/health_controller.py
+++ b/backend/app/controller/health_controller.py
@@ -1,22 +1,104 @@
from fastapi import APIRouter
from pydantic import BaseModel
+from sqlalchemy import text
from utils import traceroot_wrapper as traceroot
+import os
logger = traceroot.get_logger("health_controller")
router = APIRouter(tags=["Health"])
+# -------------------------------
+# Response Models
+# -------------------------------
+
+class DatabaseStatus(BaseModel):
+ status: str
+
+
+class ModelStatus(BaseModel):
+ configured: bool
+
+
+class ToolStatus(BaseModel):
+ available: bool
+
+
class HealthResponse(BaseModel):
status: str
service: str
+ database: DatabaseStatus
+ model: ModelStatus
+ tools: ToolStatus
+# -------------------------------
+# Health Endpoint
+# -------------------------------
+
@router.get("/health", name="health check", response_model=HealthResponse)
async def health_check():
- """Health check endpoint for verifying backend is ready to accept requests."""
+ """
+ Health & diagnostics endpoint.
+
+ Verifies:
+ - Backend availability
+ - Database connectivity
+ - Model configuration
+ - Tool registry availability
+ """
+
logger.debug("Health check requested")
- response = HealthResponse(status="ok", service="eigent")
- logger.debug("Health check completed", extra={"status": response.status, "service": response.service})
- return response
+ # -------------------------------
+ # Database check
+ # -------------------------------
+ db_status = "unknown"
+ try:
+ from app.database import engine # adjust path ONLY if needed
+ with engine.connect() as conn:
+ conn.execute(text("SELECT 1"))
+ db_status = "ok"
+ except Exception as e:
+ logger.warning("Database health check failed", extra={"error": str(e)})
+ db_status = "error"
+
+ # -------------------------------
+ # Model configuration check
+ # -------------------------------
+ model_api_key = os.getenv("MODEL_API_KEY")
+ model_name = os.getenv("MODEL_NAME")
+
+ model_configured = bool(model_api_key and model_name)
+
+ # -------------------------------
+ # Tool availability check
+ # -------------------------------
+ tools_available = False
+ try:
+ from app.tools.registry import TOOL_REGISTRY # adjust path if needed
+ tools_available = len(TOOL_REGISTRY) > 0
+ except Exception as e:
+ logger.warning("Tool registry check failed", extra={"error": str(e)})
+
+ response = HealthResponse(
+ status="ok",
+ service="eigent",
+ database=DatabaseStatus(status=db_status),
+ model=ModelStatus(configured=model_configured),
+ tools=ToolStatus(available=tools_available),
+ )
+
+ logger.debug(
+ "Health check completed",
+ extra={
+ "status": response.status,
+ "service": response.service,
+ "database": db_status,
+ "model_configured": model_configured,
+ "tools_available": tools_available,
+ },
+ )
+
+ return response
diff --git a/src/pages/Diagnostics.tsx b/src/pages/Diagnostics.tsx
new file mode 100644
index 000000000..9d367da2b
--- /dev/null
+++ b/src/pages/Diagnostics.tsx
@@ -0,0 +1,57 @@
+import { useEffect, useState } from "react";
+
+type HealthResponse = {
+ status: string;
+ service: string;
+ database: { status: string };
+ model: { configured: boolean };
+ tools: { available: boolean };
+};
+
+export default function Diagnostics() {
+ const [data, setData] = useState(null);
+ const [error, setError] = useState("");
+
+ useEffect(() => {
+ fetch("/health")
+ .then((res) => {
+ if (!res.ok) throw new Error("Backend unreachable");
+ return res.json();
+ })
+ .then(setData)
+ .catch((err) => setError(err.message));
+ }, []);
+
+ if (error) {
+ return ❌ {error}
;
+ }
+
+ if (!data) {
+ return Loading system diagnostics...
;
+ }
+
+ return (
+
+
System Diagnostics
+
+
Backend: ✅ Running
+
+
+ Database:{" "}
+ {data.database.status === "ok" ? "✅ Connected" : "❌ Error"}
+
+
+
+ Model:{" "}
+ {data.model.configured
+ ? "✅ Configured"
+ : "⚠️ Not Configured"}
+
+
+
+ Tools:{" "}
+ {data.tools.available ? "✅ Available" : "❌ Not Available"}
+
+
+ );
+}
diff --git a/src/routers/index.tsx b/src/routers/index.tsx
index 223d0a52e..10bd4093a 100644
--- a/src/routers/index.tsx
+++ b/src/routers/index.tsx
@@ -3,11 +3,13 @@ import { Routes, Route, Navigate, Outlet } from "react-router-dom";
import { useAuthStore } from "@/store/authStore";
import Layout from "@/components/Layout";
+
// Lazy load page components
const Login = lazy(() => import("@/pages/Login"));
const Signup = lazy(() => import("@/pages/SignUp"));
const Home = lazy(() => import("@/pages/Home"));
const History = lazy(() => import("@/pages/History"));
+const Diagnostics = lazy(() => import("@/pages/Diagnostics"));
const NotFound = lazy(() => import("@/pages/NotFound"));
// Route guard: Check if user is logged in
@@ -17,15 +19,16 @@ const ProtectedRoute = () => {
const [initialized, setInitialized] = useState(false);
const { token, localProxyValue, logout } = useAuthStore();
+
useEffect(() => {
// Check VITE_USE_LOCAL_PROXY value on app startup
if (token) {
const currentProxyValue = import.meta.env.VITE_USE_LOCAL_PROXY || null;
const storedProxyValue = localProxyValue;
-
+
// If stored value exists and differs from current, logout
if (storedProxyValue !== null && storedProxyValue !== currentProxyValue) {
- console.warn('VITE_USE_LOCAL_PROXY value changed, logging out user');
+ console.warn("VITE_USE_LOCAL_PROXY value changed, logging out user");
logout();
setIsAuthenticated(false);
setLoading(false);
@@ -33,12 +36,12 @@ const ProtectedRoute = () => {
return;
}
}
-
+
setIsAuthenticated(!!token);
setLoading(false);
setInitialized(true);
}, [token, localProxyValue, logout]);
-
+
if (loading || !initialized) {
return (
@@ -46,22 +49,35 @@ const ProtectedRoute = () => {
);
}
+
return isAuthenticated ? : ;
};
// Main route configuration
const AppRoutes = () => (
+ {/* Public routes */}
} />
} />
+
+ {/* Protected routes */}
}>
}>
} />
} />
- } />
- } />
+ } />
+ }
+ />
+ }
+ />
+
+ {/* Fallback */}
} />
);
From 89ed2a82bdf8e827ea5c911a8002c607ee1498c1 Mon Sep 17 00:00:00 2001
From: sambella
Date: Sun, 18 Jan 2026 22:37:14 +0530
Subject: [PATCH 2/3] Fix diagnostics page to align with backend health
response
---
backend/app/controller/health_controller.py | 61 ++-------------------
src/pages/Diagnostics.tsx | 20 ++-----
2 files changed, 8 insertions(+), 73 deletions(-)
diff --git a/backend/app/controller/health_controller.py b/backend/app/controller/health_controller.py
index 40083e8b8..9fbd5020e 100644
--- a/backend/app/controller/health_controller.py
+++ b/backend/app/controller/health_controller.py
@@ -2,61 +2,34 @@
from pydantic import BaseModel
from sqlalchemy import text
from utils import traceroot_wrapper as traceroot
-import os
logger = traceroot.get_logger("health_controller")
router = APIRouter(tags=["Health"])
-# -------------------------------
-# Response Models
-# -------------------------------
-
class DatabaseStatus(BaseModel):
status: str
-class ModelStatus(BaseModel):
- configured: bool
-
-
-class ToolStatus(BaseModel):
- available: bool
-
-
class HealthResponse(BaseModel):
status: str
service: str
database: DatabaseStatus
- model: ModelStatus
- tools: ToolStatus
-
-# -------------------------------
-# Health Endpoint
-# -------------------------------
@router.get("/health", name="health check", response_model=HealthResponse)
async def health_check():
"""
- Health & diagnostics endpoint.
-
- Verifies:
- - Backend availability
- - Database connectivity
- - Model configuration
- - Tool registry availability
+ Health check endpoint for verifying backend and database readiness.
"""
logger.debug("Health check requested")
- # -------------------------------
- # Database check
- # -------------------------------
+ # Database connectivity check
db_status = "unknown"
try:
- from app.database import engine # adjust path ONLY if needed
+ from app.database import engine # existing project database engine
with engine.connect() as conn:
conn.execute(text("SELECT 1"))
db_status = "ok"
@@ -64,41 +37,15 @@ async def health_check():
logger.warning("Database health check failed", extra={"error": str(e)})
db_status = "error"
- # -------------------------------
- # Model configuration check
- # -------------------------------
- model_api_key = os.getenv("MODEL_API_KEY")
- model_name = os.getenv("MODEL_NAME")
-
- model_configured = bool(model_api_key and model_name)
-
- # -------------------------------
- # Tool availability check
- # -------------------------------
- tools_available = False
- try:
- from app.tools.registry import TOOL_REGISTRY # adjust path if needed
- tools_available = len(TOOL_REGISTRY) > 0
- except Exception as e:
- logger.warning("Tool registry check failed", extra={"error": str(e)})
-
response = HealthResponse(
status="ok",
service="eigent",
database=DatabaseStatus(status=db_status),
- model=ModelStatus(configured=model_configured),
- tools=ToolStatus(available=tools_available),
)
logger.debug(
"Health check completed",
- extra={
- "status": response.status,
- "service": response.service,
- "database": db_status,
- "model_configured": model_configured,
- "tools_available": tools_available,
- },
+ extra={"status": response.status, "database": db_status},
)
return response
diff --git a/src/pages/Diagnostics.tsx b/src/pages/Diagnostics.tsx
index 9d367da2b..8a4e782c8 100644
--- a/src/pages/Diagnostics.tsx
+++ b/src/pages/Diagnostics.tsx
@@ -3,9 +3,9 @@ import { useEffect, useState } from "react";
type HealthResponse = {
status: string;
service: string;
- database: { status: string };
- model: { configured: boolean };
- tools: { available: boolean };
+ database: {
+ status: string;
+ };
};
export default function Diagnostics() {
@@ -13,7 +13,7 @@ export default function Diagnostics() {
const [error, setError] = useState("");
useEffect(() => {
- fetch("/health")
+ fetch("/api/health")
.then((res) => {
if (!res.ok) throw new Error("Backend unreachable");
return res.json();
@@ -40,18 +40,6 @@ export default function Diagnostics() {
Database:{" "}
{data.database.status === "ok" ? "✅ Connected" : "❌ Error"}
-
-
- Model:{" "}
- {data.model.configured
- ? "✅ Configured"
- : "⚠️ Not Configured"}
-
-
-
- Tools:{" "}
- {data.tools.available ? "✅ Available" : "❌ Not Available"}
-
);
}
From 4bea985e0cd701e92d35d43d5792befd769020d3 Mon Sep 17 00:00:00 2001
From: sambella
Date: Sun, 22 Mar 2026 15:50:08 +0530
Subject: [PATCH 3/3] Address review feedback: align health endpoint and
diagnostics page
---
backend/app/controller/health_controller.py | 24 +++-----------------
src/pages/Diagnostics.tsx | 25 +++++++++------------
2 files changed, 14 insertions(+), 35 deletions(-)
diff --git a/backend/app/controller/health_controller.py b/backend/app/controller/health_controller.py
index 9fbd5020e..793cd110f 100644
--- a/backend/app/controller/health_controller.py
+++ b/backend/app/controller/health_controller.py
@@ -1,6 +1,5 @@
from fastapi import APIRouter
from pydantic import BaseModel
-from sqlalchemy import text
from utils import traceroot_wrapper as traceroot
logger = traceroot.get_logger("health_controller")
@@ -8,44 +7,27 @@
router = APIRouter(tags=["Health"])
-class DatabaseStatus(BaseModel):
- status: str
-
-
class HealthResponse(BaseModel):
status: str
service: str
- database: DatabaseStatus
@router.get("/health", name="health check", response_model=HealthResponse)
async def health_check():
"""
- Health check endpoint for verifying backend and database readiness.
+ Health check endpoint for verifying backend readiness.
"""
logger.debug("Health check requested")
- # Database connectivity check
- db_status = "unknown"
- try:
- from app.database import engine # existing project database engine
- with engine.connect() as conn:
- conn.execute(text("SELECT 1"))
- db_status = "ok"
- except Exception as e:
- logger.warning("Database health check failed", extra={"error": str(e)})
- db_status = "error"
-
response = HealthResponse(
status="ok",
service="eigent",
- database=DatabaseStatus(status=db_status),
)
logger.debug(
"Health check completed",
- extra={"status": response.status, "database": db_status},
+ extra={"status": response.status, "service": response.service},
)
- return response
+ return response
\ No newline at end of file
diff --git a/src/pages/Diagnostics.tsx b/src/pages/Diagnostics.tsx
index 8a4e782c8..bf112cc84 100644
--- a/src/pages/Diagnostics.tsx
+++ b/src/pages/Diagnostics.tsx
@@ -1,11 +1,16 @@
+/*
+ * Copyright 2024 Eigent
+ *
+ * Licensed under the Apache License, Version 2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
import { useEffect, useState } from "react";
+import { fetchGet } from "@/api/http";
type HealthResponse = {
status: string;
service: string;
- database: {
- status: string;
- };
};
export default function Diagnostics() {
@@ -13,11 +18,7 @@ export default function Diagnostics() {
const [error, setError] = useState("");
useEffect(() => {
- fetch("/api/health")
- .then((res) => {
- if (!res.ok) throw new Error("Backend unreachable");
- return res.json();
- })
+ fetchGet("/health")
.then(setData)
.catch((err) => setError(err.message));
}, []);
@@ -35,11 +36,7 @@ export default function Diagnostics() {
System Diagnostics
Backend: ✅ Running
-
-
- Database:{" "}
- {data.database.status === "ok" ? "✅ Connected" : "❌ Error"}
-
+ Service: {data.service}
);
-}
+}
\ No newline at end of file