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

153 lines 4.81 kB
/** * Server Utilities for NeuroLink CLI * Shared utility functions for server management commands (serve.ts and server.ts) */ import fs from "fs"; import os from "os"; import path from "path"; // ============================================ // State Directory Management // ============================================ /** * Get the base directory for NeuroLink state files * @returns Path to ~/.neurolink directory */ export function getNeuroLinkDir() { return path.join(os.homedir(), ".neurolink"); } /** * Ensure the NeuroLink state directory exists * Creates ~/.neurolink if it doesn't exist */ export function ensureStateDir() { const dir = getNeuroLinkDir(); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } // ============================================ // Process Management // ============================================ /** * Check if a process with the given PID is currently running * * Uses `process.kill(pid, 0)` which tests if a process exists without sending a signal. * * **Platform Behavior:** * - **Unix/Linux/macOS**: Returns `true` if process exists, `false` if not. * If the process exists but belongs to another user, returns `true` (via EPERM check). * - **Windows**: Behavior differs - `process.kill(pid, 0)` may throw even for existing * processes if they are system processes or have restricted access. This function * handles EPERM by returning `true`, but other Windows-specific errors may occur. * For more reliable Windows process detection, consider using `tasklist` command. * * @param pid - Process ID to check * @returns true if the process is running, false otherwise */ export function isProcessRunning(pid) { try { // Sending signal 0 tests if process exists without actually sending a signal process.kill(pid, 0); return true; } catch (err) { const code = err.code; // EPERM means process exists but we lack permission to send signals to it return code === "EPERM"; } } // ============================================ // Time Formatting // ============================================ /** * Format a duration in milliseconds to a human-readable uptime string * @param ms - Duration in milliseconds * @returns Formatted string like "2d 5h 30m" or "45m 30s" */ export function formatUptime(ms) { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (days > 0) { return `${days}d ${hours % 24}h ${minutes % 60}m`; } if (hours > 0) { return `${hours}h ${minutes % 60}m ${seconds % 60}s`; } if (minutes > 0) { return `${minutes}m ${seconds % 60}s`; } return `${seconds}s`; } // ============================================ // Generic State File Management // ============================================ /** * Generic state file manager for server state persistence * @template T - Type of the state object */ export class StateFileManager { filePath; /** * Create a new state file manager * @param filename - Name of the state file (e.g., "serve-state.json") * @param baseDir - Optional base directory (defaults to ~/.neurolink) */ constructor(filename, baseDir) { this.filePath = path.join(baseDir ?? getNeuroLinkDir(), filename); } /** * Get the full path to the state file */ getFilePath() { return this.filePath; } /** * Save state to the state file * @param state - State object to save */ save(state) { const dir = path.dirname(this.filePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true, mode: 0o700 }); } fs.writeFileSync(this.filePath, JSON.stringify(state, null, 2)); } /** * Load state from the state file * @returns The state object, or null if the file doesn't exist or is invalid */ load() { try { if (fs.existsSync(this.filePath)) { const content = fs.readFileSync(this.filePath, "utf8"); return JSON.parse(content); } } catch { // Ignore errors - return null for missing or invalid files } return null; } /** * Clear (delete) the state file */ clear() { try { if (fs.existsSync(this.filePath)) { fs.unlinkSync(this.filePath); } } catch { // Ignore errors when clearing } } /** * Check if state file exists */ exists() { return fs.existsSync(this.filePath); } } //# sourceMappingURL=serverUtils.js.map