sendManualInterrupt
codebolt.terminal.sendManualInterrupt(): Promise<TerminalInterruptResponse>
Sends a manual interrupt signal (SIGINT) to the terminal to cancel or stop a currently running command. This method is equivalent to pressing Ctrl+C in a terminal and is useful for stopping long-running processes or commands that need to be terminated.
Response Structure
The method returns a Promise that resolves to a TerminalInterruptResponse
object with the following properties:
TerminalInterruptResponse
type
(string): Always "terminalInterrupted".success
(boolean): Indicates whether the interrupt signal was successfully sent.message
(string, optional): Additional information about the interrupt operation or any issues encountered.
Examples
// Example 1: Basic interrupt usage
const interruptRunningCommand = async () => {
try {
const interruptResult = await codebolt.terminal.sendManualInterrupt();
if (interruptResult.success) {
console.log('✅ Command interrupted successfully');
console.log('Response type:', interruptResult.type);
if (interruptResult.message) {
console.log('Message:', interruptResult.message);
}
} else {
console.log('❌ Failed to interrupt command');
console.log('Message:', interruptResult.message);
}
return interruptResult;
} catch (error) {
console.error('❌ Exception during interrupt:', error.message);
throw error;
}
};
// Usage
await interruptRunningCommand();
// Example 2: Interrupt long-running server
const startAndStopServer = async () => {
// Start a long-running server
const serverEmitter = codebolt.terminal.executeCommandWithStream('npm run dev');
serverEmitter.on('commandOutput', (data) => {
console.log('🖥️ Server output:', data.output);
// Check if server is ready
if (data.output.includes('Server running') || data.output.includes('listening')) {
console.log('🚀 Server is ready');
}
});
serverEmitter.on('commandError', (error) => {
console.error('❌ Server error:', error.error);
});
serverEmitter.on('commandFinish', (finish) => {
console.log('🏁 Server stopped');
console.log('Exit code:', finish.exitCode);
});
// Stop the server after 10 seconds
setTimeout(async () => {
console.log('⏰ Stopping server after 10 seconds...');
try {
const interruptResult = await codebolt.terminal.sendManualInterrupt();
if (interruptResult.success) {
console.log('✅ Server interrupt signal sent successfully');
} else {
console.log('❌ Failed to send interrupt signal');
}
} catch (error) {
console.error('❌ Failed to interrupt server:', error.message);
}
}, 10000);
return serverEmitter;
};
// Example 3: Emergency stop with error detection
const emergencyStopOnError = () => {
const buildEmitter = codebolt.terminal.executeCommandWithStream('npm run build');
buildEmitter.on('commandOutput', (data) => {
console.log('🔨 Build output:', data.output);
// Emergency stop if we detect a fatal error condition
if (data.output.includes('FATAL ERROR') ||
data.output.includes('Out of memory') ||
data.output.includes('EMFILE')) {
console.log('🚨 Fatal error detected, emergency stop!');
codebolt.terminal.sendManualInterrupt()
.then(result => {
if (result.success) {
console.log('🛑 Emergency stop successful');
} else {
console.log('❌ Emergency stop failed');
}
})
.catch(error => {
console.error('❌ Emergency stop exception:', error.message);
});
}
});
buildEmitter.on('commandError', (error) => {
console.error('❌ Build error:', error.error);
});
buildEmitter.on('commandFinish', (finish) => {
console.log('🏁 Build process ended');
console.log('Exit code:', finish.exitCode);
});
return buildEmitter;
};
// Example 4: Timeout protection with automatic interrupt
const runCommandWithTimeout = (command, timeoutMs = 30000) => {
console.log(`🔄 Running command with ${timeoutMs}ms timeout: ${command}`);
const emitter = codebolt.terminal.executeCommandWithStream(command);
let commandFinished = false;
// Set up timeout
const timeout = setTimeout(async () => {
if (!commandFinished) {
console.log('⏰ Command timeout reached, interrupting...');
try {
const interruptResult = await codebolt.terminal.sendManualInterrupt();
if (interruptResult.success) {
console.log('✅ Timeout interrupt successful');
} else {
console.log('❌ Timeout interrupt failed:', interruptResult.message);
}
} catch (error) {
console.error('❌ Timeout interrupt exception:', error.message);
}
}
}, timeoutMs);
emitter.on('commandOutput', (data) => {
console.log('📡 Output:', data.output);
});
emitter.on('commandError', (error) => {
console.error('❌ Error:', error.error);
});
emitter.on('commandFinish', (finish) => {
commandFinished = true;
clearTimeout(timeout);
console.log('🏁 Command finished');
console.log('Exit code:', finish.exitCode);
if (finish.exitCode === 0) {
console.log('✅ Command completed successfully within timeout');
} else {
console.log('❌ Command failed or was interrupted');
}
});
return {
emitter,
interrupt: async () => {
clearTimeout(timeout);
return await codebolt.terminal.sendManualInterrupt();
}
};
};
// Usage
const { emitter: cmdEmitter, interrupt } = runCommandWithTimeout('npm run build', 15000);
// Manual interrupt if needed
// await interrupt();
// Example 5: Graceful shutdown sequence
const gracefulShutdown = async (processes) => {
console.log('🔄 Starting graceful shutdown sequence...');
for (let i = 0; i < processes.length; i++) {
const process = processes[i];
console.log(`[${i + 1}/${processes.length}] Stopping ${process.name}...`);
try {
// Send interrupt signal
const interruptResult = await codebolt.terminal.sendManualInterrupt();
if (interruptResult.success) {
console.log(`✅ ${process.name} interrupt signal sent`);
// Wait for process to stop gracefully
await new Promise(resolve => setTimeout(resolve, process.gracePeriod || 2000));
console.log(`✅ ${process.name} graceful shutdown completed`);
} else {
console.log(`❌ Failed to interrupt ${process.name}: ${interruptResult.message}`);
}
} catch (error) {
console.error(`❌ Exception stopping ${process.name}:`, error.message);
}
}
console.log('🎉 Graceful shutdown sequence completed');
};
// Usage
const runningProcesses = [
{ name: 'Development Server', gracePeriod: 3000 },
{ name: 'Background Worker', gracePeriod: 2000 },
{ name: 'File Watcher', gracePeriod: 1000 }
];
// await gracefulShutdown(runningProcesses);
// Example 6: Interactive command management
const interactiveCommandManager = () => {
let currentCommand = null;
let commandHistory = [];
const startCommand = (command) => {
if (currentCommand) {
console.log('⚠️ Another command is already running. Stop it first.');
return null;
}
console.log(`🚀 Starting: ${command}`);
currentCommand = {
command,
emitter: codebolt.terminal.executeCommandWithStream(command),
startTime: Date.now()
};
currentCommand.emitter.on('commandOutput', (data) => {
console.log('📡', data.output);
});
currentCommand.emitter.on('commandError', (error) => {
console.error('❌', error.error);
});
currentCommand.emitter.on('commandFinish', (finish) => {
const duration = Date.now() - currentCommand.startTime;
console.log('🏁 Command finished');
console.log(`Duration: ${Math.round(duration / 1000)}s`);
console.log(`Exit code: ${finish.exitCode}`);
commandHistory.push({
command: currentCommand.command,
duration: Math.round(duration / 1000),
exitCode: finish.exitCode,
timestamp: new Date().toISOString()
});
currentCommand = null;
});
return currentCommand;
};
const stopCommand = async () => {
if (!currentCommand) {
console.log('⚠️ No command is currently running');
return { success: false, message: 'No active command' };
}
console.log(`🛑 Stopping: ${currentCommand.command}`);
try {
const interruptResult = await codebolt.terminal.sendManualInterrupt();
if (interruptResult.success) {
console.log('✅ Stop signal sent successfully');
} else {
console.log('❌ Failed to send stop signal');
}
return interruptResult;
} catch (error) {
console.error('❌ Exception stopping command:', error.message);
return { success: false, message: error.message };
}
};
const getStatus = () => {
return {
currentCommand: currentCommand ? {
command: currentCommand.command,
duration: Math.round((Date.now() - currentCommand.startTime) / 1000)
} : null,
history: commandHistory
};
};
return {
start: startCommand,
stop: stopCommand,
status: getStatus
};
};
// Usage
const manager = interactiveCommandManager();
// Start a command
manager.start('npm run dev');
// Check status
console.log('Current status:', manager.status());
// Stop the command after some time
setTimeout(async () => {
const stopResult = await manager.stop();
console.log('Stop result:', stopResult);
}, 5000);
// Example 7: Batch interrupt for multiple processes
const interruptMultipleProcesses = async (processNames = []) => {
console.log('🔄 Interrupting multiple processes...');
const results = [];
for (let i = 0; i < processNames.length; i++) {
const processName = processNames[i];
console.log(`[${i + 1}/${processNames.length}] Interrupting ${processName}...`);
try {
const interruptResult = await codebolt.terminal.sendManualInterrupt();
results.push({
processName,
success: interruptResult.success,
message: interruptResult.message,
timestamp: new Date().toISOString()
});
if (interruptResult.success) {
console.log(`✅ ${processName} interrupted successfully`);
} else {
console.log(`❌ Failed to interrupt ${processName}: ${interruptResult.message}`);
}
// Small delay between interrupts
if (i < processNames.length - 1) {
await new Promise(resolve => setTimeout(resolve, 500));
}
} catch (error) {
console.error(`❌ Exception interrupting ${processName}:`, error.message);
results.push({
processName,
success: false,
message: error.message,
timestamp: new Date().toISOString(),
exception: true
});
}
}
// Summary
const successful = results.filter(r => r.success).length;
const failed = results.filter(r => !r.success).length;
console.log('📊 Interrupt Summary:');
console.log(` ✅ Successful: ${successful}`);
console.log(` ❌ Failed: ${failed}`);
console.log(` 📈 Success rate: ${Math.round(successful / results.length * 100)}%`);
return results;
};
// Usage
const processesToStop = ['Development Server', 'API Server', 'Background Worker'];
const interruptResults = await interruptMultipleProcesses(processesToStop);
// Example 8: Smart interrupt with retry logic
const smartInterrupt = async (maxRetries = 3, retryDelay = 1000) => {
let attempt = 1;
while (attempt <= maxRetries) {
console.log(`🔄 Interrupt attempt ${attempt}/${maxRetries}...`);
try {
const interruptResult = await codebolt.terminal.sendManualInterrupt();
if (interruptResult.success) {
console.log(`✅ Interrupt successful on attempt ${attempt}`);
return {
success: true,
attempts: attempt,
result: interruptResult
};
} else {
console.log(`❌ Interrupt failed on attempt ${attempt}: ${interruptResult.message}`);
if (attempt < maxRetries) {
console.log(`⏳ Retrying in ${retryDelay}ms...`);
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
}
} catch (error) {
console.error(`❌ Exception on attempt ${attempt}:`, error.message);
if (attempt < maxRetries) {
console.log(`⏳ Retrying in ${retryDelay}ms...`);
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
}
attempt++;
}
console.log(`❌ All ${maxRetries} interrupt attempts failed`);
return {
success: false,
attempts: maxRetries,
message: 'All retry attempts exhausted'
};
};
// Usage
const smartResult = await smartInterrupt(3, 2000);
console.log('Smart interrupt result:', smartResult);
Common Use Cases
- Development Server Management: Stop development servers when switching projects or configurations
- Build Process Control: Cancel long-running build processes that are stuck or taking too long
- Emergency Stops: Immediately stop processes that are consuming too many resources or causing issues
- Timeout Protection: Automatically stop commands that exceed expected execution time
- Graceful Shutdown: Implement proper shutdown sequences for applications with multiple processes
- Interactive Development: Provide users with the ability to stop long-running operations
- Error Recovery: Stop processes when error conditions are detected
- Resource Management: Stop processes to free up system resources when needed
Notes
- The interrupt signal is equivalent to pressing Ctrl+C in a terminal
- Not all processes may respond to SIGINT signals immediately
- Some processes may have cleanup routines that run before terminating
- The method only sends the interrupt signal; it doesn't guarantee immediate process termination
- Use this method responsibly as it can cause data loss in processes that don't handle interrupts gracefully
- Consider implementing graceful shutdown procedures before using force interrupts
- The success response indicates the signal was sent, not that the process actually stopped
- Some system processes or privileged operations may not be interruptible
- Always handle both successful and failed interrupt attempts in your code