vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
73 lines (72 loc) • 2.48 kB
JavaScript
import chalk from 'chalk';
import { SessionPersistence } from './persistence.js';
import logger from '../../logger.js';
export class GracefulShutdown {
handlers = [];
isShuttingDown = false;
register(handler) {
this.handlers.push(handler);
}
async execute() {
if (this.isShuttingDown) {
return;
}
this.isShuttingDown = true;
console.log();
console.log(chalk.yellow('Shutting down...'));
const timeout = 5000;
const handlerPromises = this.handlers.map(handler => Promise.race([
handler(),
new Promise((_, reject) => setTimeout(() => reject(new Error('Shutdown timeout')), timeout))
]).catch(error => {
logger.error({ err: error }, 'Shutdown handler error');
}));
await Promise.all(handlerPromises);
console.log(chalk.green('Goodbye! 👋'));
process.exit(0);
}
setupSignalHandlers() {
process.on('SIGINT', async () => {
await this.execute();
});
process.on('SIGTERM', async () => {
await this.execute();
});
process.on('uncaughtException', async (error) => {
console.error(chalk.red('Uncaught exception:'), error);
logger.error({ err: error }, 'Uncaught exception in interactive mode');
await this.execute();
});
process.on('unhandledRejection', async (reason, promise) => {
console.error(chalk.red('Unhandled rejection:'), reason);
logger.error({ reason, promise }, 'Unhandled rejection in interactive mode');
await this.execute();
});
}
}
export function createAutoSaveHandler(sessionId, getSessionData, interval = 60000) {
const persistence = new SessionPersistence();
let intervalId = null;
const save = async () => {
try {
await persistence.saveSession(sessionId, getSessionData());
logger.debug({ sessionId }, 'Session auto-saved');
}
catch (error) {
logger.error({ err: error, sessionId }, 'Failed to auto-save session');
}
};
return {
start: () => {
save();
intervalId = setInterval(save, interval);
},
stop: async () => {
if (intervalId) {
clearInterval(intervalId);
intervalId = null;
}
await save();
}
};
}