bonzai-burn 1.0.40 → 1.0.45

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/dist/index.js CHANGED
@@ -21,9 +21,9 @@ var init_loops_config = __esm({
21
21
  CHANNELS = {
22
22
  dev: ["burn", "visualization", "backend"],
23
23
  beta: ["burn", "visualization"],
24
- stable: ["burn"]
24
+ stable: ["burn", "visualization"]
25
25
  };
26
- channel = "dev";
26
+ channel = "stable";
27
27
  ENABLED_LOOPS = CHANNELS[channel];
28
28
  }
29
29
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bonzai-burn",
3
- "version": "1.0.40",
3
+ "version": "1.0.45",
4
4
  "description": "Git branch-based cleanup tool with bburn, baccept, and brevert commands",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,20 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { ROOT } = require('../config');
4
-
5
- function deleteHandler(req, res) {
6
- try {
7
- const targetPath = path.join(ROOT, req.body.path || '');
8
- if (!targetPath.startsWith(ROOT)) {
9
- return res.status(400).send('Invalid path');
10
- }
11
- // Delete file or directory recursively
12
- fs.rmSync(targetPath, { recursive: true, force: true });
13
- res.json({ status: 'ok' });
14
- } catch (e) {
15
- res.status(500).send(e.message);
16
- }
17
- }
18
-
19
- module.exports = deleteHandler;
20
-
@@ -1,72 +0,0 @@
1
- const { execSync } = require('child_process');
2
-
3
- // GET /git/burns - List all bonzai-burn branches
4
- function listBurns(req, res) {
5
- try {
6
- // Get all bonzai-burn branches
7
- let branchOutput;
8
- try {
9
- branchOutput = execSync('git branch --list "bonzai-burn*"', { encoding: 'utf-8' });
10
- } catch (e) {
11
- // No matching branches
12
- branchOutput = '';
13
- }
14
-
15
- const branches = branchOutput
16
- .split('\n')
17
- .filter(b => b.trim())
18
- .map(b => b.trim().replace('* ', ''));
19
-
20
- if (branches.length === 0) {
21
- return res.json({ burns: [] });
22
- }
23
-
24
- // Get timestamp for each branch
25
- const burns = branches.map(branch => {
26
- const timestamp = execSync(`git log -1 --format=%at ${branch}`, { encoding: 'utf-8' }).trim();
27
- return {
28
- name: branch,
29
- timestamp: parseInt(timestamp) * 1000
30
- };
31
- });
32
-
33
- // Sort chronologically (oldest first)
34
- burns.sort((a, b) => a.timestamp - b.timestamp);
35
-
36
- // Get current branch
37
- const currentBranch = execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
38
-
39
- res.json({
40
- burns: burns.map(b => ({
41
- ...b,
42
- current: b.name === currentBranch
43
- }))
44
- });
45
- } catch (error) {
46
- res.status(500).json({ error: error.message });
47
- }
48
- }
49
-
50
- // POST /git/checkout - Checkout a branch
51
- function checkoutBranch(req, res) {
52
- try {
53
- const { branchName } = req.body;
54
-
55
- if (!branchName) {
56
- return res.status(400).json({ error: 'branchName is required' });
57
- }
58
-
59
- // Validate branch name to prevent command injection
60
- if (!/^[a-zA-Z0-9_\-\.\/]+$/.test(branchName)) {
61
- return res.status(400).json({ error: 'Invalid branch name' });
62
- }
63
-
64
- execSync(`git checkout ${branchName}`, { encoding: 'utf-8' });
65
-
66
- res.json({ checkedOut: branchName });
67
- } catch (error) {
68
- res.status(500).json({ error: error.message });
69
- }
70
- }
71
-
72
- module.exports = { listBurns, checkoutBranch };
@@ -1,108 +0,0 @@
1
- const path = require('path');
2
- const { exec } = require('child_process');
3
- const { ROOT } = require('../config');
4
-
5
- function openCursorHandler(req, res) {
6
- try {
7
- const requestedPath = req.body.path || '';
8
-
9
- // Resolve path relative to ROOT (similar to other endpoints)
10
- // If path is absolute and within ROOT, use it directly
11
- // Otherwise, resolve it relative to ROOT
12
- let filePath;
13
- if (path.isAbsolute(requestedPath)) {
14
- // If absolute path, check if it's within ROOT
15
- if (requestedPath.startsWith(ROOT)) {
16
- filePath = requestedPath;
17
- } else {
18
- // Path might contain incorrect segments (like "codemaps")
19
- // Try to find ROOT in the path and extract the relative part
20
- const rootIndex = requestedPath.indexOf(ROOT);
21
- if (rootIndex !== -1) {
22
- // Extract the part after ROOT and remove leading slashes
23
- let relativePart = requestedPath.substring(rootIndex + ROOT.length);
24
- while (relativePart.startsWith('/')) {
25
- relativePart = relativePart.substring(1);
26
- }
27
- filePath = path.join(ROOT, relativePart);
28
- } else {
29
- return res.status(400).json({ error: 'Invalid path: path must be within project root' });
30
- }
31
- }
32
- } else {
33
- // Relative path - resolve relative to ROOT
34
- // Remove root directory name prefix if present (from /list endpoint format)
35
- const rootName = path.basename(ROOT);
36
- let relativePath = requestedPath;
37
- if (relativePath.startsWith(rootName + '/')) {
38
- relativePath = relativePath.substring(rootName.length + 1);
39
- }
40
- filePath = path.join(ROOT, relativePath);
41
- }
42
-
43
- // Validate the resolved path is within ROOT
44
- if (!filePath.startsWith(ROOT)) {
45
- return res.status(400).json({ error: 'Invalid path' });
46
- }
47
-
48
- const { line } = req.body;
49
-
50
- // Always use cursor CLI command first (it handles line numbers correctly)
51
- const cursorCommands = [
52
- 'cursor',
53
- '/Applications/Cursor.app/Contents/Resources/app/bin/cursor',
54
- '/usr/local/bin/cursor',
55
- 'code'
56
- ];
57
-
58
- const tryCommand = (commandIndex = 0) => {
59
- if (commandIndex >= cursorCommands.length) {
60
- return res.status(500).json({
61
- error: 'Cursor not found. Please install Cursor CLI or check Cursor installation.'
62
- });
63
- }
64
-
65
- // Use proper Cursor CLI syntax for line numbers
66
- const command = line
67
- ? `${cursorCommands[commandIndex]} --goto "${filePath}:${line}"`
68
- : `${cursorCommands[commandIndex]} "${filePath}"`;
69
-
70
- exec(command, (error, stdout, stderr) => {
71
- if (error && error.code === 127) {
72
- // Command not found, try next one
73
- tryCommand(commandIndex + 1);
74
- } else if (error) {
75
- console.error('Error opening Cursor:', error);
76
- return res.status(500).json({ error: error.message });
77
- } else {
78
- // File opened successfully, now bring Cursor to front
79
- const isMac = process.platform === 'darwin';
80
- if (isMac) {
81
- // Use AppleScript to bring Cursor to the front
82
- exec('osascript -e "tell application \\"Cursor\\" to activate"', (activateError) => {
83
- if (activateError) {
84
- console.log('Could not activate Cursor, but file opened successfully');
85
- }
86
- });
87
-
88
- // Additional command to ensure it's really in front
89
- setTimeout(() => {
90
- exec('osascript -e "tell application \\"System Events\\" to set frontmost of process \\"Cursor\\" to true"', () => {
91
- // Don't worry if this fails
92
- });
93
- }, 500);
94
- }
95
-
96
- res.json({ success: true, message: 'Cursor opened and focused successfully' });
97
- }
98
- });
99
- };
100
-
101
- tryCommand();
102
- } catch (e) {
103
- res.status(500).json({ error: e.message });
104
- }
105
- }
106
-
107
- module.exports = openCursorHandler;
108
-
@@ -1,16 +0,0 @@
1
- function shutdownHandler(req, res) {
2
- console.log('🛑 Shutdown endpoint called - terminating server...');
3
-
4
- res.json({
5
- success: true,
6
- message: 'Server shutting down...'
7
- });
8
-
9
- // Close the server gracefully
10
- setTimeout(() => {
11
- process.exit(0);
12
- }, 100); // Small delay to ensure response is sent
13
- }
14
-
15
- module.exports = shutdownHandler;
16
-
@@ -1,140 +0,0 @@
1
- let pty;
2
- try {
3
- pty = require('node-pty');
4
- } catch (err) {
5
- pty = null;
6
- }
7
-
8
- // Store active terminal sessions
9
- const terminals = new Map();
10
-
11
- // Get default shell based on platform
12
- function getDefaultShell() {
13
- if (process.platform === 'win32') {
14
- return process.env.COMSPEC || 'powershell.exe';
15
- }
16
- const shell = process.env.SHELL || '/bin/bash';
17
- if (!shell.startsWith('/')) {
18
- return '/bin/bash';
19
- }
20
- return shell;
21
- }
22
-
23
- // Create a new terminal session
24
- function createTerminal(sessionId, cols = 80, rows = 24) {
25
- if (!pty) {
26
- throw new Error('node-pty is not available. Native binaries may not have installed correctly.');
27
- }
28
-
29
- const shell = getDefaultShell();
30
- const cwd = process.env.BONZAI_REPO_DIR || process.cwd();
31
-
32
- let ptyProcess;
33
- try {
34
- ptyProcess = pty.spawn(shell, [], {
35
- name: 'xterm-256color',
36
- cols,
37
- rows,
38
- cwd,
39
- env: {
40
- ...process.env,
41
- TERM: 'xterm-256color',
42
- PATH: process.env.PATH || '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'
43
- }
44
- });
45
- } catch (spawnErr) {
46
- try {
47
- ptyProcess = pty.spawn('/bin/bash', [], {
48
- name: 'xterm-256color',
49
- cols,
50
- rows,
51
- cwd,
52
- env: {
53
- ...process.env,
54
- TERM: 'xterm-256color',
55
- PATH: process.env.PATH || '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'
56
- }
57
- });
58
- } catch (bashErr) {
59
- throw spawnErr;
60
- }
61
- }
62
-
63
- terminals.set(sessionId, {
64
- pty: ptyProcess,
65
- buffer: ''
66
- });
67
-
68
- return ptyProcess;
69
- }
70
-
71
- // HTTP handler for terminal info
72
- function terminalHandler(req, res) {
73
- res.json({
74
- message: 'Terminal WebSocket API',
75
- usage: {
76
- websocket: 'ws://localhost:3001/terminal',
77
- events: {
78
- 'input': 'Send terminal input (data: string)',
79
- 'resize': 'Resize terminal (cols: number, rows: number)',
80
- 'output': 'Receive terminal output'
81
- }
82
- }
83
- });
84
- }
85
-
86
- // WebSocket handler for terminal sessions
87
- function setupTerminalWebSocket(wss) {
88
- wss.on('connection', (ws) => {
89
- const sessionId = Date.now().toString();
90
- let ptyProcess;
91
-
92
- try {
93
- ptyProcess = createTerminal(sessionId);
94
- } catch (err) {
95
- ws.send(JSON.stringify({ type: 'error', message: 'Failed to create terminal: ' + err.message }));
96
- ws.close();
97
- return;
98
- }
99
-
100
- // Send terminal output to WebSocket client
101
- ptyProcess.onData((data) => {
102
- try {
103
- ws.send(JSON.stringify({ type: 'output', data }));
104
- } catch (e) {
105
- // Client disconnected
106
- }
107
- });
108
-
109
- ptyProcess.onExit(({ exitCode }) => {
110
- ws.send(JSON.stringify({ type: 'exit', exitCode }));
111
- ws.close();
112
- });
113
-
114
- // Handle incoming messages from client
115
- ws.on('message', (message) => {
116
- try {
117
- const msg = JSON.parse(message);
118
-
119
- switch (msg.type) {
120
- case 'input':
121
- ptyProcess.write(msg.data);
122
- break;
123
- case 'resize':
124
- ptyProcess.resize(msg.cols, msg.rows);
125
- break;
126
- }
127
- } catch (e) {
128
- // Parse error
129
- }
130
- });
131
-
132
- // Cleanup on disconnect
133
- ws.on('close', () => {
134
- ptyProcess.kill();
135
- terminals.delete(sessionId);
136
- });
137
- });
138
- }
139
-
140
- module.exports = { terminalHandler, setupTerminalWebSocket };
@@ -1,18 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { ROOT } = require('../config');
4
-
5
- function writeHandler(req, res) {
6
- try {
7
- const filePath = path.join(ROOT, req.body.path || '');
8
- if (!filePath.startsWith(ROOT)) {
9
- return res.status(400).send('Invalid path');
10
- }
11
- fs.writeFileSync(filePath, req.body.content, 'utf8');
12
- res.json({ status: 'ok' });
13
- } catch (e) {
14
- res.status(500).send(e.message);
15
- }
16
- }
17
-
18
- module.exports = writeHandler;