UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

234 lines (233 loc) 10.7 kB
/** * Health Routes * Endpoints for health checks and system status */ import { withSpan } from "../../telemetry/withSpan.js"; import { tracers } from "../../telemetry/tracers.js"; /** * Wrap a health-route handler with an OTel span that records the route, * request id, and overall health status. */ function tracedHealthHandler(name, route, fn) { return (ctx) => withSpan({ name, tracer: tracers.http, attributes: { "http.route": route, "http.request.id": ctx.requestId ?? "", }, }, () => fn(ctx)); } /** * Create health check routes */ export function createHealthRoutes(basePath = "/api") { return { prefix: `${basePath}/health`, routes: [ { method: "GET", path: `${basePath}/health`, handler: tracedHealthHandler("neurolink.http.health.check", `${basePath}/health`, async () => { return { status: "ok", timestamp: new Date().toISOString(), uptime: process.uptime() * 1000, version: process.env.npm_package_version || "unknown", }; }), description: "Basic health check", tags: ["health"], }, { method: "GET", path: `${basePath}/health/live`, handler: tracedHealthHandler("neurolink.http.health.live", `${basePath}/health/live`, async () => { // Liveness probe - just checks if the server is running return { status: "alive", timestamp: new Date().toISOString(), }; }), description: "Kubernetes liveness probe", tags: ["health"], }, { method: "GET", path: `${basePath}/health/ready`, handler: (ctx) => withSpan({ name: "neurolink.http.health.ready", tracer: tracers.http, attributes: { "http.route": `${basePath}/health/ready`, "http.request.id": ctx.requestId ?? "", }, }, async (span) => { // Readiness probe - checks if all dependencies are ready const tools = await ctx.toolRegistry.listTools(); const hasTools = tools.length > 0; const hasExternalManager = !!ctx.externalServerManager; // Check external servers if available let externalServersReady = true; if (ctx.externalServerManager) { const statuses = ctx.externalServerManager.getServerStatuses(); for (const status of statuses) { if (status.status !== "connected") { externalServersReady = false; break; } } } const isReady = hasTools || !hasExternalManager || externalServersReady; span.setAttribute("health.ready", isReady); span.setAttribute("health.tools_count", tools.length); span.setAttribute("health.external_servers_ready", externalServersReady); return { ready: isReady, timestamp: new Date().toISOString(), services: { neurolink: true, tools: hasTools, externalServers: externalServersReady, }, }; }), description: "Kubernetes readiness probe", tags: ["health"], }, { method: "GET", path: `${basePath}/health/startup`, handler: (ctx) => withSpan({ name: "neurolink.http.health.startup", tracer: tracers.http, attributes: { "http.route": `${basePath}/health/startup`, "http.request.id": ctx.requestId ?? "", }, }, async (span) => { // Startup probe - checks if the application has started successfully const tools = await ctx.toolRegistry.listTools(); span.setAttribute("health.tools_count", tools.length); return { started: true, timestamp: new Date().toISOString(), services: { neurolink: true, toolsLoaded: tools.length, externalServerManager: !!ctx.externalServerManager, }, }; }), description: "Kubernetes startup probe", tags: ["health"], }, { method: "GET", path: `${basePath}/health/detailed`, handler: (ctx) => withSpan({ name: "neurolink.http.health.detailed", tracer: tracers.http, attributes: { "http.route": `${basePath}/health/detailed`, "http.request.id": ctx.requestId ?? "", }, }, async (span) => { const tools = await ctx.toolRegistry.listTools(); // Group tools by source const toolsBySource = {}; for (const tool of tools) { const source = typeof tool.source === "string" ? tool.source : tool.serverId || "built-in"; toolsBySource[source] = (toolsBySource[source] || 0) + 1; } // Get external server statuses const externalServers = []; if (ctx.externalServerManager) { const statuses = ctx.externalServerManager.getServerStatuses(); for (const status of statuses) { externalServers.push({ name: status.serverId, status: status.status, toolCount: status.toolCount, }); } } // Memory status const memory = ctx.neurolink.conversationMemory; const memoryStatus = { available: !!memory, type: memory?.constructor.name || "none", }; // Build the base health response const healthResponse = { status: "ok", timestamp: new Date().toISOString(), uptime: process.uptime() * 1000, version: process.env.npm_package_version || "unknown", node: { version: process.version, platform: process.platform, arch: process.arch, }, memory: { ...memoryStatus, process: { heapUsed: Math.round(process.memoryUsage().heapUsed / 1024 / 1024), heapTotal: Math.round(process.memoryUsage().heapTotal / 1024 / 1024), rss: Math.round(process.memoryUsage().rss / 1024 / 1024), external: Math.round(process.memoryUsage().external / 1024 / 1024), }, }, tools: { total: tools.length, bySource: toolsBySource, }, externalServers: { count: externalServers.length, servers: externalServers, }, }; // Add proxy account pool status when proxy mode is active if (ctx.metadata?.accountPool) { const pool = ctx.metadata.accountPool; const allAccounts = pool.getAllAccounts(); const statusCounts = {}; for (const a of allAccounts) { statusCounts[a.status] = (statusCounts[a.status] || 0) + 1; } healthResponse.proxy = { totalAccounts: allAccounts.length, statusDistribution: statusCounts, healthyCount: pool.getHealthyCount(), strategy: pool.getStrategy(), }; span.setAttribute("health.proxy.accounts", allAccounts.length); span.setAttribute("health.proxy.healthy", pool.getHealthyCount()); } span.setAttribute("health.tools_count", tools.length); span.setAttribute("health.external_servers_count", externalServers.length); span.setAttribute("health.memory.heap_mb", Math.round(process.memoryUsage().heapUsed / 1024 / 1024)); return healthResponse; }), description: "Detailed health information", tags: ["health"], }, { method: "GET", path: `${basePath}/version`, handler: tracedHealthHandler("neurolink.http.version", `${basePath}/version`, async () => { return { name: "@juspay/neurolink", version: process.env.npm_package_version || "unknown", node: process.version, timestamp: new Date().toISOString(), }; }), description: "Get version information", tags: ["health", "version"], }, ], }; }