Skip to content

Commit d6c81ff

Browse files
davila7claude
andcommitted
Add E2B sandbox execution confirmation and ESC cancellation
Features added: ✅ Sandbox Execution Confirmation: - Beautiful formatted confirmation dialog with execution details - Shows agent name, truncated prompt, provider (E2B Cloud) - Displays execution info: real-time logs, file downloads, timeout - Clear ESC cancellation instructions ✅ ESC Key Cancellation: - Real-time ESC key detection during sandbox execution - Graceful process termination with SIGTERM - Proper stdin cleanup and raw mode handling - User-friendly cancellation messages ✅ Enhanced User Experience: - Informative confirmation dialog before execution - Real-time execution status and instructions - Safe process cancellation without hanging - Clear feedback for all execution states This provides users with full control over sandbox execution and clear visibility into what will happen during the E2B sandbox process. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 73ca583 commit d6c81ff

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

cli-tool/src/index.js

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2123,6 +2123,33 @@ async function executeSandbox(options, targetDir) {
21232123
return;
21242124
}
21252125

2126+
// Sandbox execution confirmation
2127+
console.log(chalk.blue('\n☁️ E2B Sandbox Execution'));
2128+
console.log(chalk.cyan('═══════════════════════════════════════'));
2129+
console.log(chalk.white(`📋 Agent: ${chalk.yellow(agent || 'default')}`));
2130+
const truncatedPrompt = prompt.length > 80 ? prompt.substring(0, 80) + '...' : prompt;
2131+
console.log(chalk.white(`💭 Prompt: ${chalk.cyan('"' + truncatedPrompt + '"')}`));
2132+
console.log(chalk.white(`🌐 Provider: ${chalk.green('E2B Cloud')}`));
2133+
console.log(chalk.gray('\n🔧 Execution details:'));
2134+
console.log(chalk.gray(' • Execution logs will be displayed in real-time'));
2135+
console.log(chalk.gray(' • Files will be downloaded to ./e2b-outputs/ folder'));
2136+
console.log(chalk.gray(' • Extended timeout: 15 minutes for complex operations'));
2137+
console.log(chalk.yellow(' • Press ESC anytime to cancel execution\n'));
2138+
2139+
const inquirer = require('inquirer');
2140+
2141+
const { shouldExecuteSandbox } = await inquirer.prompt([{
2142+
type: 'confirm',
2143+
name: 'shouldExecuteSandbox',
2144+
message: `Execute this agent in E2B sandbox?`,
2145+
default: true
2146+
}]);
2147+
2148+
if (!shouldExecuteSandbox) {
2149+
console.log(chalk.yellow('⏹️ E2B sandbox execution cancelled by user.'));
2150+
return;
2151+
}
2152+
21262153
try {
21272154
console.log(chalk.blue('🔮 Setting up E2B sandbox environment...'));
21282155

@@ -2240,6 +2267,9 @@ async function executeSandbox(options, targetDir) {
22402267
}
22412268

22422269
// Execute sandbox and wait for completion
2270+
console.log(chalk.blue('🚀 Starting E2B sandbox execution...'));
2271+
console.log(chalk.yellow('💡 Press ESC anytime to cancel the execution'));
2272+
22432273
await new Promise((resolve, reject) => {
22442274
const sandboxExecution = spawn(pythonCmd, [
22452275
path.join(sandboxDir, 'e2b-launcher.py'),
@@ -2258,11 +2288,41 @@ async function executeSandbox(options, targetDir) {
22582288
}
22592289
});
22602290

2291+
// Setup ESC key listener for cancellation
2292+
process.stdin.setRawMode(true);
2293+
process.stdin.resume();
2294+
process.stdin.setEncoding('utf8');
2295+
2296+
const keyListener = (key) => {
2297+
// ESC key (ASCII 27)
2298+
if (key === '\u001b') {
2299+
console.log(chalk.yellow('\n⏹️ Cancelling E2B sandbox execution...'));
2300+
sandboxExecution.kill('SIGTERM');
2301+
2302+
// Cleanup
2303+
process.stdin.setRawMode(false);
2304+
process.stdin.pause();
2305+
process.stdin.removeListener('data', keyListener);
2306+
2307+
resolve(); // Resolve to prevent hanging
2308+
}
2309+
};
2310+
2311+
process.stdin.on('data', keyListener);
2312+
22612313
sandboxExecution.on('close', (sandboxCode) => {
2314+
// Cleanup stdin listener
2315+
process.stdin.setRawMode(false);
2316+
process.stdin.pause();
2317+
process.stdin.removeListener('data', keyListener);
2318+
22622319
if (sandboxCode === 0) {
22632320
console.log(chalk.green('🎉 Sandbox execution completed successfully!'));
22642321
console.log(chalk.blue('💡 Files were created inside the E2B sandbox environment'));
22652322
resolve();
2323+
} else if (sandboxCode === null) {
2324+
console.log(chalk.yellow('⏹️ Sandbox execution was cancelled'));
2325+
resolve();
22662326
} else {
22672327
console.log(chalk.yellow(`⚠️ Sandbox execution finished with exit code ${sandboxCode}`));
22682328
console.log(chalk.gray('💡 Check the output above for any error details'));
@@ -2271,6 +2331,11 @@ async function executeSandbox(options, targetDir) {
22712331
});
22722332

22732333
sandboxExecution.on('error', (error) => {
2334+
// Cleanup stdin listener
2335+
process.stdin.setRawMode(false);
2336+
process.stdin.pause();
2337+
process.stdin.removeListener('data', keyListener);
2338+
22742339
if (error.code === 'TIMEOUT') {
22752340
console.log(chalk.yellow('⏱️ Sandbox execution timed out after 15 minutes'));
22762341
console.log(chalk.gray('💡 This may happen with very complex prompts or large projects'));

0 commit comments

Comments
 (0)