devbonzai 2.0.3 → 2.0.5
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 +97 -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,49 @@ 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
|
+
// Capture initial state of modified files (files already dirty before job starts)
|
|
1298
|
+
const initiallyModifiedFiles = new Set();
|
|
1299
|
+
try {
|
|
1300
|
+
const initialStatus = execSync('git status --short', { cwd: ROOT }).toString();
|
|
1301
|
+
initialStatus.split('\\n').filter(Boolean).forEach(line => {
|
|
1302
|
+
const filePath = line.substring(3).trim();
|
|
1303
|
+
if (filePath) initiallyModifiedFiles.add(filePath);
|
|
1304
|
+
});
|
|
1305
|
+
console.log('🔵 [prompt_agent] Initially modified files:', Array.from(initiallyModifiedFiles));
|
|
1306
|
+
} catch (e) {
|
|
1307
|
+
console.log('⚠️ [prompt_agent] Could not get initial status:', e.message);
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
// Set up file change tracking - only track NEW changes during job
|
|
1311
|
+
const changedFiles = new Set();
|
|
1312
|
+
const pollInterval = setInterval(() => {
|
|
1313
|
+
try {
|
|
1314
|
+
const status = execSync('git status --short', { cwd: ROOT }).toString();
|
|
1315
|
+
status.split('\\n').filter(Boolean).forEach(line => {
|
|
1316
|
+
const filePath = line.substring(3).trim(); // Remove status prefix (XY + space)
|
|
1317
|
+
// Only add if this file was NOT already modified before the job started
|
|
1318
|
+
if (filePath && !initiallyModifiedFiles.has(filePath)) {
|
|
1319
|
+
const wasNew = !changedFiles.has(filePath);
|
|
1320
|
+
changedFiles.add(filePath);
|
|
1321
|
+
if (wasNew) {
|
|
1322
|
+
console.log('📁 [prompt_agent] New file changed:', filePath);
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
});
|
|
1326
|
+
} catch (e) {
|
|
1327
|
+
// Ignore git status errors
|
|
1328
|
+
}
|
|
1329
|
+
}, 500);
|
|
1330
|
+
|
|
1287
1331
|
// Configurable timeout (default 5 minutes)
|
|
1288
1332
|
const timeoutMs = parseInt(req.body.timeout) || 5 * 60 * 1000;
|
|
1289
1333
|
let timeoutId = null;
|
|
@@ -1312,6 +1356,7 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1312
1356
|
timeoutId = setTimeout(() => {
|
|
1313
1357
|
if (!responseSent && proc && !proc.killed) {
|
|
1314
1358
|
console.log('⏱️ [prompt_agent] Timeout reached, killing process...');
|
|
1359
|
+
clearInterval(pollInterval);
|
|
1315
1360
|
proc.kill('SIGTERM');
|
|
1316
1361
|
|
|
1317
1362
|
// Force kill after a short grace period if SIGTERM doesn't work
|
|
@@ -1329,7 +1374,10 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1329
1374
|
message: \`cursor-agent exceeded timeout of \${timeoutMs / 1000} seconds\`,
|
|
1330
1375
|
code: -1,
|
|
1331
1376
|
stdout,
|
|
1332
|
-
stderr
|
|
1377
|
+
stderr,
|
|
1378
|
+
changedFiles: Array.from(changedFiles),
|
|
1379
|
+
beforeCommit,
|
|
1380
|
+
afterCommit: ''
|
|
1333
1381
|
});
|
|
1334
1382
|
}
|
|
1335
1383
|
}
|
|
@@ -1349,6 +1397,7 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1349
1397
|
|
|
1350
1398
|
proc.on('error', (error) => {
|
|
1351
1399
|
console.log('❌ [prompt_agent] Process error:', error.message);
|
|
1400
|
+
clearInterval(pollInterval);
|
|
1352
1401
|
if (timeoutId) clearTimeout(timeoutId);
|
|
1353
1402
|
if (!responseSent) {
|
|
1354
1403
|
responseSent = true;
|
|
@@ -1361,8 +1410,19 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1361
1410
|
console.log('🔵 [prompt_agent] stdout length:', stdout.length);
|
|
1362
1411
|
console.log('🔵 [prompt_agent] stderr length:', stderr.length);
|
|
1363
1412
|
|
|
1413
|
+
// Stop polling for file changes
|
|
1414
|
+
clearInterval(pollInterval);
|
|
1364
1415
|
if (timeoutId) clearTimeout(timeoutId);
|
|
1365
1416
|
|
|
1417
|
+
// Capture afterCommit
|
|
1418
|
+
let afterCommit = '';
|
|
1419
|
+
try {
|
|
1420
|
+
afterCommit = execSync('git rev-parse HEAD', { cwd: ROOT }).toString().trim();
|
|
1421
|
+
console.log('🔵 [prompt_agent] afterCommit:', afterCommit);
|
|
1422
|
+
} catch (e) {
|
|
1423
|
+
console.log('⚠️ [prompt_agent] Could not get afterCommit:', e.message);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1366
1426
|
if (!responseSent) {
|
|
1367
1427
|
responseSent = true;
|
|
1368
1428
|
// Check if process was killed due to timeout
|
|
@@ -1372,19 +1432,52 @@ app.post('/prompt_agent', (req, res) => {
|
|
|
1372
1432
|
message: signal === 'SIGTERM' ? 'Process was terminated due to timeout' : 'Process was force killed',
|
|
1373
1433
|
code: code || -1,
|
|
1374
1434
|
stdout,
|
|
1375
|
-
stderr
|
|
1435
|
+
stderr,
|
|
1436
|
+
changedFiles: Array.from(changedFiles),
|
|
1437
|
+
beforeCommit,
|
|
1438
|
+
afterCommit
|
|
1376
1439
|
});
|
|
1377
1440
|
} else {
|
|
1378
1441
|
res.json({
|
|
1379
1442
|
code,
|
|
1380
1443
|
stdout,
|
|
1381
|
-
stderr
|
|
1444
|
+
stderr,
|
|
1445
|
+
changedFiles: Array.from(changedFiles),
|
|
1446
|
+
beforeCommit,
|
|
1447
|
+
afterCommit
|
|
1382
1448
|
});
|
|
1383
1449
|
}
|
|
1384
1450
|
}
|
|
1385
1451
|
});
|
|
1386
1452
|
});
|
|
1387
1453
|
|
|
1454
|
+
// Revert job endpoint to reset to a previous commit
|
|
1455
|
+
app.post('/revert_job', (req, res) => {
|
|
1456
|
+
console.log('🔵 [revert_job] Endpoint hit');
|
|
1457
|
+
const { beforeCommit } = req.body;
|
|
1458
|
+
|
|
1459
|
+
if (!beforeCommit || typeof beforeCommit !== 'string') {
|
|
1460
|
+
console.log('❌ [revert_job] Error: beforeCommit required');
|
|
1461
|
+
return res.status(400).json({ error: 'beforeCommit required' });
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
// Validate commit hash format (basic sanitization to prevent command injection)
|
|
1465
|
+
if (!/^[a-f0-9]{7,40}$/i.test(beforeCommit)) {
|
|
1466
|
+
console.log('❌ [revert_job] Error: invalid commit hash format');
|
|
1467
|
+
return res.status(400).json({ error: 'Invalid commit hash format' });
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
try {
|
|
1471
|
+
console.log('🔵 [revert_job] Resetting to commit:', beforeCommit);
|
|
1472
|
+
execSync(\`git reset --hard \${beforeCommit}\`, { cwd: ROOT });
|
|
1473
|
+
console.log('✅ [revert_job] Successfully reverted to commit:', beforeCommit);
|
|
1474
|
+
res.json({ success: true });
|
|
1475
|
+
} catch (e) {
|
|
1476
|
+
console.log('❌ [revert_job] Error:', e.message);
|
|
1477
|
+
res.status(500).json({ error: e.message });
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
|
|
1388
1481
|
// Shutdown endpoint to kill the server
|
|
1389
1482
|
app.post('/shutdown', (req, res) => {
|
|
1390
1483
|
console.log('🛑 Shutdown endpoint called - terminating server...');
|