devbonzai 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +80 -4
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -64,7 +64,7 @@ const express = require('./node_modules/express');
|
|
|
64
64
|
const cors = require('./node_modules/cors');
|
|
65
65
|
const fs = require('fs');
|
|
66
66
|
const path = require('path');
|
|
67
|
-
const { exec, spawn } = require('child_process');
|
|
67
|
+
const { exec, spawn, execSync } = require('child_process');
|
|
68
68
|
let babelParser = null;
|
|
69
69
|
try {
|
|
70
70
|
babelParser = require('./node_modules/@babel/parser');
|
|
@@ -92,6 +92,7 @@ app.get('/', (req, res) => {
|
|
|
92
92
|
'POST /move': 'Move file or folder (body: {source, destination})',
|
|
93
93
|
'POST /open-cursor': 'Open Cursor (body: {path, line?})',
|
|
94
94
|
'POST /prompt_agent': 'Execute cursor-agent command (body: {prompt})',
|
|
95
|
+
'POST /revert_job': 'Revert to a previous commit (body: {beforeCommit})',
|
|
95
96
|
'POST /shutdown': 'Gracefully shutdown the server'
|
|
96
97
|
},
|
|
97
98
|
example: 'Try: /list or /read?path=README.md'
|
|
@@ -1284,6 +1285,32 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1284
1285
|
return res.status(400).json({ error: 'prompt required' });
|
|
1285
1286
|
}
|
|
1286
1287
|
|
|
1288
|
+
// Capture beforeCommit
|
|
1289
|
+
let beforeCommit = '';
|
|
1290
|
+
try {
|
|
1291
|
+
beforeCommit = execSync('git rev-parse HEAD', { cwd: ROOT }).toString().trim();
|
|
1292
|
+
console.log('🔵 [prompt_agent] beforeCommit:', beforeCommit);
|
|
1293
|
+
} catch (e) {
|
|
1294
|
+
console.log('⚠️ [prompt_agent] Could not get beforeCommit:', e.message);
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
// Set up file change tracking
|
|
1298
|
+
const changedFiles = new Set();
|
|
1299
|
+
const pollInterval = setInterval(() => {
|
|
1300
|
+
try {
|
|
1301
|
+
const status = execSync('git status --short', { cwd: ROOT }).toString();
|
|
1302
|
+
status.split('\\n').filter(Boolean).forEach(line => {
|
|
1303
|
+
const filePath = line.substring(3).trim(); // Remove status prefix (XY + space)
|
|
1304
|
+
if (filePath) changedFiles.add(filePath);
|
|
1305
|
+
});
|
|
1306
|
+
if (changedFiles.size > 0) {
|
|
1307
|
+
console.log('📁 [prompt_agent] Changed files:', Array.from(changedFiles));
|
|
1308
|
+
}
|
|
1309
|
+
} catch (e) {
|
|
1310
|
+
// Ignore git status errors
|
|
1311
|
+
}
|
|
1312
|
+
}, 500);
|
|
1313
|
+
|
|
1287
1314
|
// Configurable timeout (default 5 minutes)
|
|
1288
1315
|
const timeoutMs = parseInt(req.body.timeout) || 5 * 60 * 1000;
|
|
1289
1316
|
let timeoutId = null;
|
|
@@ -1312,6 +1339,7 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1312
1339
|
timeoutId = setTimeout(() => {
|
|
1313
1340
|
if (!responseSent && proc && !proc.killed) {
|
|
1314
1341
|
console.log('⏱️ [prompt_agent] Timeout reached, killing process...');
|
|
1342
|
+
clearInterval(pollInterval);
|
|
1315
1343
|
proc.kill('SIGTERM');
|
|
1316
1344
|
|
|
1317
1345
|
// Force kill after a short grace period if SIGTERM doesn't work
|
|
@@ -1329,7 +1357,10 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1329
1357
|
message: \`cursor-agent exceeded timeout of \${timeoutMs / 1000} seconds\`,
|
|
1330
1358
|
code: -1,
|
|
1331
1359
|
stdout,
|
|
1332
|
-
stderr
|
|
1360
|
+
stderr,
|
|
1361
|
+
changedFiles: Array.from(changedFiles),
|
|
1362
|
+
beforeCommit,
|
|
1363
|
+
afterCommit: ''
|
|
1333
1364
|
});
|
|
1334
1365
|
}
|
|
1335
1366
|
}
|
|
@@ -1349,6 +1380,7 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1349
1380
|
|
|
1350
1381
|
proc.on('error', (error) => {
|
|
1351
1382
|
console.log('❌ [prompt_agent] Process error:', error.message);
|
|
1383
|
+
clearInterval(pollInterval);
|
|
1352
1384
|
if (timeoutId) clearTimeout(timeoutId);
|
|
1353
1385
|
if (!responseSent) {
|
|
1354
1386
|
responseSent = true;
|
|
@@ -1361,8 +1393,19 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1361
1393
|
console.log('🔵 [prompt_agent] stdout length:', stdout.length);
|
|
1362
1394
|
console.log('🔵 [prompt_agent] stderr length:', stderr.length);
|
|
1363
1395
|
|
|
1396
|
+
// Stop polling for file changes
|
|
1397
|
+
clearInterval(pollInterval);
|
|
1364
1398
|
if (timeoutId) clearTimeout(timeoutId);
|
|
1365
1399
|
|
|
1400
|
+
// Capture afterCommit
|
|
1401
|
+
let afterCommit = '';
|
|
1402
|
+
try {
|
|
1403
|
+
afterCommit = execSync('git rev-parse HEAD', { cwd: ROOT }).toString().trim();
|
|
1404
|
+
console.log('🔵 [prompt_agent] afterCommit:', afterCommit);
|
|
1405
|
+
} catch (e) {
|
|
1406
|
+
console.log('⚠️ [prompt_agent] Could not get afterCommit:', e.message);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1366
1409
|
if (!responseSent) {
|
|
1367
1410
|
responseSent = true;
|
|
1368
1411
|
// Check if process was killed due to timeout
|
|
@@ -1372,19 +1415,52 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1372
1415
|
message: signal === 'SIGTERM' ? 'Process was terminated due to timeout' : 'Process was force killed',
|
|
1373
1416
|
code: code || -1,
|
|
1374
1417
|
stdout,
|
|
1375
|
-
stderr
|
|
1418
|
+
stderr,
|
|
1419
|
+
changedFiles: Array.from(changedFiles),
|
|
1420
|
+
beforeCommit,
|
|
1421
|
+
afterCommit
|
|
1376
1422
|
});
|
|
1377
1423
|
} else {
|
|
1378
1424
|
res.json({
|
|
1379
1425
|
code,
|
|
1380
1426
|
stdout,
|
|
1381
|
-
stderr
|
|
1427
|
+
stderr,
|
|
1428
|
+
changedFiles: Array.from(changedFiles),
|
|
1429
|
+
beforeCommit,
|
|
1430
|
+
afterCommit
|
|
1382
1431
|
});
|
|
1383
1432
|
}
|
|
1384
1433
|
}
|
|
1385
1434
|
});
|
|
1386
1435
|
});
|
|
1387
1436
|
|
|
1437
|
+
// Revert job endpoint to reset to a previous commit
|
|
1438
|
+
app.post('/revert_job', (req, res) => {
|
|
1439
|
+
console.log('🔵 [revert_job] Endpoint hit');
|
|
1440
|
+
const { beforeCommit } = req.body;
|
|
1441
|
+
|
|
1442
|
+
if (!beforeCommit || typeof beforeCommit !== 'string') {
|
|
1443
|
+
console.log('❌ [revert_job] Error: beforeCommit required');
|
|
1444
|
+
return res.status(400).json({ error: 'beforeCommit required' });
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
// Validate commit hash format (basic sanitization to prevent command injection)
|
|
1448
|
+
if (!/^[a-f0-9]{7,40}$/i.test(beforeCommit)) {
|
|
1449
|
+
console.log('❌ [revert_job] Error: invalid commit hash format');
|
|
1450
|
+
return res.status(400).json({ error: 'Invalid commit hash format' });
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
try {
|
|
1454
|
+
console.log('🔵 [revert_job] Resetting to commit:', beforeCommit);
|
|
1455
|
+
execSync(\`git reset --hard \${beforeCommit}\`, { cwd: ROOT });
|
|
1456
|
+
console.log('✅ [revert_job] Successfully reverted to commit:', beforeCommit);
|
|
1457
|
+
res.json({ success: true });
|
|
1458
|
+
} catch (e) {
|
|
1459
|
+
console.log('❌ [revert_job] Error:', e.message);
|
|
1460
|
+
res.status(500).json({ error: e.message });
|
|
1461
|
+
}
|
|
1462
|
+
});
|
|
1463
|
+
|
|
1388
1464
|
// Shutdown endpoint to kill the server
|
|
1389
1465
|
app.post('/shutdown', (req, res) => {
|
|
1390
1466
|
console.log('🛑 Shutdown endpoint called - terminating server...');
|