import { StatusManager } from '../core/status-manager'; export interface SlashCommandOptions { statusManager: StatusManager; /** List of authorized user IDs */ authorizedUsers: string[]; /** Cooldown duration in seconds */ cooldownSeconds?: number; /** Callback for replies */ onReply: (message: string) => Promise; } interface CommandState { passMgrEnabled: boolean; safeRestartEnabled: boolean; lastToggle: { 'pass-mgr': number; 'safe-restart': number; }; } export class SlashCommandHandler { private statusManager: StatusManager; private authorizedUsers: string[]; private cooldownMs: number; private onReply: (message: string) => Promise; private state: CommandState; constructor(options: SlashCommandOptions) { this.statusManager = options.statusManager; this.authorizedUsers = options.authorizedUsers; this.cooldownMs = (options.cooldownSeconds || 10) * 1000; this.onReply = options.onReply; this.state = { passMgrEnabled: true, safeRestartEnabled: true, lastToggle: { 'pass-mgr': 0, 'safe-restart': 0, }, }; } /** * Handle a slash command */ async handle(command: string, userId: string): Promise { // Check authorization if (!this.authorizedUsers.includes(userId)) { await this.onReply('Unauthorized'); return; } const parts = command.trim().split(/\s+/); const subcommand = parts[1]; const feature = parts[2] as 'pass-mgr' | 'safe-restart'; switch (subcommand) { case 'status': await this.handleStatus(); break; case 'enable': await this.handleEnable(feature); break; case 'disable': await this.handleDisable(feature); break; default: await this.onReply( 'Usage:\n' + '`/padded-cell-ctrl status` - Show status\n' + '`/padded-cell-ctrl enable pass-mgr|safe-restart` - Enable feature\n' + '`/padded-cell-ctrl disable pass-mgr|safe-restart` - Disable feature' ); } } private async handleStatus(): Promise { const global = this.statusManager.getGlobalStatus(); const agents = this.statusManager.getAllAgents(); const lines = [ '**PaddedCell Status**', '', `Secret Manager: ${this.state.passMgrEnabled ? 'Enabled' : 'Disabled'}`, `Safe Restart: ${this.state.safeRestartEnabled ? 'Enabled' : 'Disabled'}`, '', '**Agent Status:**', ]; for (const agent of agents) { const emoji = this.getStateEmoji(agent.state); lines.push(`${emoji} ${agent.agentId}: ${agent.state}`); } if (agents.length === 0) { lines.push('(No agents registered)'); } if (global.restartStatus !== 'idle') { lines.push(''); lines.push(`Restart Status: ${global.restartStatus}`); if (global.restartScheduledBy) { lines.push(` Initiated by ${global.restartScheduledBy}`); } } await this.onReply(lines.join('\n')); } private async handleEnable(feature: 'pass-mgr' | 'safe-restart'): Promise { if (!this.isValidFeature(feature)) { await this.onReply('Unknown feature. Available: pass-mgr, safe-restart'); return; } if (this.isOnCooldown(feature)) { await this.onReply('This feature was recently modified. Please try again later.'); return; } if (feature === 'pass-mgr') { this.state.passMgrEnabled = true; } else { this.state.safeRestartEnabled = true; } this.state.lastToggle[feature] = Date.now(); await this.onReply(`Enabled ${feature}`); } private async handleDisable(feature: 'pass-mgr' | 'safe-restart'): Promise { if (!this.isValidFeature(feature)) { await this.onReply('Unknown feature. Available: pass-mgr, safe-restart'); return; } if (this.isOnCooldown(feature)) { await this.onReply('This feature was recently modified. Please try again later.'); return; } if (feature === 'pass-mgr') { this.state.passMgrEnabled = false; } else { this.state.safeRestartEnabled = false; } this.state.lastToggle[feature] = Date.now(); await this.onReply(`Disabled ${feature}`); } private isValidFeature(feature: string): feature is 'pass-mgr' | 'safe-restart' { return feature === 'pass-mgr' || feature === 'safe-restart'; } private isOnCooldown(feature: 'pass-mgr' | 'safe-restart'): boolean { const lastToggle = this.state.lastToggle[feature]; return Date.now() - lastToggle < this.cooldownMs; } private getStateEmoji(state: string): string { switch (state) { case 'idle': return '💤'; case 'busy': return '⚡'; case 'focus': return '🎯'; case 'freeze': return '🧊'; case 'pre-freeze': return '⏳'; case 'pre-freeze-focus': return '📝'; default: return '❓'; } } isPassMgrEnabled(): boolean { return this.state.passMgrEnabled; } isSafeRestartEnabled(): boolean { return this.state.safeRestartEnabled; } }