devbonzai 2.1.2 → 2.1.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.
@@ -1,147 +0,0 @@
1
- const path = require('path');
2
- const { exec } = require('child_process');
3
-
4
- function setupInfraRoutes(app, ROOT) {
5
- // GET / - Root route with API documentation
6
- app.get('/', (req, res) => {
7
- res.json({
8
- message: 'Local File Server API',
9
- endpoints: {
10
- 'GET /list': 'List all files in the directory',
11
- 'GET /read?path=<filepath>': 'Read file content',
12
- 'POST /write': 'Write file content (body: {path, content})',
13
- 'POST /write_dir': 'Create directory (body: {path})',
14
- 'POST /delete': 'Delete file or directory (body: {path})',
15
- 'POST /move': 'Move file or folder (body: {source, destination})',
16
- 'POST /open-cursor': 'Open Cursor (body: {path, line?})',
17
- 'POST /analyze_prompt': 'Analyze what files would be modified (body: {prompt})',
18
- 'POST /prompt_agent': 'Execute cursor-agent command (body: {prompt})',
19
- 'POST /prompt_agent_stream': 'Execute cursor-agent with SSE streaming (body: {prompt})',
20
- 'POST /revert_job': 'Revert to a previous commit (body: {beforeCommit})',
21
- 'POST /shutdown': 'Gracefully shutdown the server'
22
- },
23
- example: 'Try: /list or /read?path=README.md'
24
- });
25
- });
26
-
27
- // POST /open-cursor - Open file in Cursor IDE
28
- app.post('/open-cursor', (req, res) => {
29
- try {
30
- const requestedPath = req.body.path || '';
31
-
32
- // Resolve path relative to ROOT (similar to other endpoints)
33
- // If path is absolute and within ROOT, use it directly
34
- // Otherwise, resolve it relative to ROOT
35
- let filePath;
36
- if (path.isAbsolute(requestedPath)) {
37
- // If absolute path, check if it's within ROOT
38
- if (requestedPath.startsWith(ROOT)) {
39
- filePath = requestedPath;
40
- } else {
41
- // Path might contain incorrect segments (like "codemaps")
42
- // Try to find ROOT in the path and extract the relative part
43
- const rootIndex = requestedPath.indexOf(ROOT);
44
- if (rootIndex !== -1) {
45
- // Extract the part after ROOT and remove leading slashes
46
- let relativePart = requestedPath.substring(rootIndex + ROOT.length);
47
- while (relativePart.startsWith('/')) {
48
- relativePart = relativePart.substring(1);
49
- }
50
- filePath = path.join(ROOT, relativePart);
51
- } else {
52
- return res.status(400).json({ error: 'Invalid path: path must be within project root' });
53
- }
54
- }
55
- } else {
56
- // Relative path - resolve relative to ROOT
57
- // Remove root directory name prefix if present (from /list endpoint format)
58
- const rootName = path.basename(ROOT);
59
- let relativePath = requestedPath;
60
- if (relativePath.startsWith(rootName + '/')) {
61
- relativePath = relativePath.substring(rootName.length + 1);
62
- }
63
- filePath = path.join(ROOT, relativePath);
64
- }
65
-
66
- // Validate the resolved path is within ROOT
67
- if (!filePath.startsWith(ROOT)) {
68
- return res.status(400).json({ error: 'Invalid path' });
69
- }
70
-
71
- const { line } = req.body;
72
-
73
- // Always use cursor CLI command first (it handles line numbers correctly)
74
- const cursorCommands = [
75
- 'cursor',
76
- '/Applications/Cursor.app/Contents/Resources/app/bin/cursor',
77
- '/usr/local/bin/cursor',
78
- 'code'
79
- ];
80
-
81
- const tryCommand = (commandIndex = 0) => {
82
- if (commandIndex >= cursorCommands.length) {
83
- return res.status(500).json({
84
- error: 'Cursor not found. Please install Cursor CLI or check Cursor installation.'
85
- });
86
- }
87
-
88
- // Use proper Cursor CLI syntax for line numbers
89
- const command = line
90
- ? `${cursorCommands[commandIndex]} --goto "${filePath}:${line}"`
91
- : `${cursorCommands[commandIndex]} "${filePath}"`;
92
-
93
- exec(command, (error, stdout, stderr) => {
94
- if (error && error.code === 127) {
95
- // Command not found, try next one
96
- tryCommand(commandIndex + 1);
97
- } else if (error) {
98
- console.error('Error opening Cursor:', error);
99
- return res.status(500).json({ error: error.message });
100
- } else {
101
- // File opened successfully, now bring Cursor to front
102
- const isMac = process.platform === 'darwin';
103
- if (isMac) {
104
- // Use AppleScript to bring Cursor to the front
105
- exec('osascript -e "tell application \\"Cursor\\" to activate"', (activateError) => {
106
- if (activateError) {
107
- console.log('Could not activate Cursor, but file opened successfully');
108
- }
109
- });
110
-
111
- // Additional command to ensure it's really in front
112
- setTimeout(() => {
113
- exec('osascript -e "tell application \\"System Events\\" to set frontmost of process \\"Cursor\\" to true"', () => {
114
- // Don't worry if this fails
115
- });
116
- }, 500);
117
- }
118
-
119
- res.json({ success: true, message: 'Cursor opened and focused successfully' });
120
- }
121
- });
122
- };
123
-
124
- tryCommand();
125
- } catch (e) {
126
- res.status(500).json({ error: e.message });
127
- }
128
- });
129
-
130
- // POST /shutdown - Gracefully shutdown the server
131
- app.post('/shutdown', (req, res) => {
132
- console.log('🛑 Shutdown endpoint called - terminating server...');
133
-
134
- res.json({
135
- success: true,
136
- message: 'Server shutting down...'
137
- });
138
-
139
- // Close the server gracefully
140
- setTimeout(() => {
141
- process.exit(0);
142
- }, 100); // Small delay to ensure response is sent
143
- });
144
- }
145
-
146
- module.exports = { setupInfraRoutes };
147
-
@@ -1,96 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { getIgnorePatterns, shouldIgnore } = require('./ignore-patterns');
4
- const { extractPythonFunctions, extractJavaScriptFunctions, extractVueFunctions } = require('./parsers');
5
-
6
- // Recursively list all files in a directory, respecting ignore patterns
7
- function listAllFiles(dir, base = '', ignorePatterns = null) {
8
- if (ignorePatterns === null) {
9
- ignorePatterns = getIgnorePatterns();
10
- }
11
-
12
- let results = [];
13
- const list = fs.readdirSync(dir);
14
-
15
- for (const file of list) {
16
- const fullPath = path.join(dir, file);
17
- const relativePath = path.join(base, file);
18
-
19
- // Check if this path should be ignored
20
- if (shouldIgnore(relativePath, ignorePatterns)) {
21
- continue;
22
- }
23
-
24
- const stat = fs.statSync(fullPath);
25
- if (stat && stat.isDirectory()) {
26
- // Skip node_modules directories explicitly
27
- if (file === 'node_modules' || relativePath.includes('node_modules/')) {
28
- continue;
29
- }
30
- // Add the directory itself to results
31
- results.push(relativePath + '/');
32
- // Recursively list files inside the directory
33
- results = results.concat(listAllFiles(fullPath, relativePath, ignorePatterns));
34
- } else {
35
- // Skip files in node_modules explicitly
36
- if (relativePath.includes('node_modules/') || fullPath.includes('node_modules')) {
37
- continue;
38
- }
39
-
40
- results.push(relativePath);
41
-
42
- // Helper function to add functions, classes, and methods as virtual files
43
- const addVirtualFiles = (parseResult, filePath) => {
44
- // Add functions
45
- for (const func of parseResult.functions) {
46
- const functionFileName = func.name + '.function';
47
- const functionFilePath = path.join(filePath, functionFileName).replace(/\\/g, '/');
48
- results.push(functionFilePath);
49
- }
50
-
51
- // Add classes and their methods
52
- for (const cls of parseResult.classes) {
53
- // Add class itself (optional, but useful)
54
- const className = cls.name + '.class';
55
- const classFilePath = path.join(filePath, className).replace(/\\/g, '/');
56
- results.push(classFilePath);
57
-
58
- // Add methods nested under the class: ClassName.methodName
59
- if (cls.methods && cls.methods.length > 0) {
60
- for (const method of cls.methods) {
61
- const methodFileName = method.name + '.method';
62
- const methodFilePath = path.join(classFilePath, methodFileName).replace(/\\/g, '/');
63
- results.push(methodFilePath);
64
- }
65
- }
66
- }
67
- };
68
-
69
- // Handle Python files
70
- if (file.endsWith('.py')) {
71
- const parseResult = extractPythonFunctions(fullPath);
72
- addVirtualFiles(parseResult, relativePath);
73
- }
74
-
75
- // Handle JavaScript/TypeScript files
76
- // Skip .d.ts files (TypeScript declaration files) and .min.js files (minified)
77
- if ((file.endsWith('.js') || file.endsWith('.jsx') || file.endsWith('.ts') || file.endsWith('.tsx')) &&
78
- !file.endsWith('.d.ts') && !file.endsWith('.min.js')) {
79
- const parseResult = extractJavaScriptFunctions(fullPath);
80
- addVirtualFiles(parseResult, relativePath);
81
- }
82
-
83
- // Handle Vue files
84
- if (file.endsWith('.vue')) {
85
- const parseResult = extractVueFunctions(fullPath);
86
- addVirtualFiles(parseResult, relativePath);
87
- }
88
- }
89
- }
90
- return results;
91
- }
92
-
93
- module.exports = {
94
- listAllFiles
95
- };
96
-
@@ -1,53 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- // Read and parse ignore patterns from .ignore file
5
- function getIgnorePatterns() {
6
- try {
7
- const ignorePath = path.join(__dirname, '..', '.ignore');
8
- if (fs.existsSync(ignorePath)) {
9
- const content = fs.readFileSync(ignorePath, 'utf8');
10
- return content
11
- .split('\n')
12
- .map(line => line.trim())
13
- .filter(line => line && !line.startsWith('#'))
14
- .map(pattern => {
15
- // Convert simple glob patterns to regex
16
- if (pattern.endsWith('/')) {
17
- // Directory pattern
18
- pattern = pattern.slice(0, -1);
19
- }
20
-
21
- // Simple approach: escape dots and convert globs
22
- pattern = pattern.replace(/\./g, '\\.');
23
- pattern = pattern.replace(/\*\*/g, '|||DOUBLESTAR|||');
24
- pattern = pattern.replace(/\*/g, '[^/]*');
25
- pattern = pattern.replace(/\|\|\|DOUBLESTAR\|\|\|/g, '.*');
26
-
27
- return new RegExp('^' + pattern + '(/.*)?$');
28
- });
29
- }
30
- } catch (e) {
31
- console.warn('Could not read .ignore file:', e.message);
32
- }
33
-
34
- // Default ignore patterns if no .ignore file exists
35
- return [
36
- /^node_modules(\/.*)?$/,
37
- /^\.git(\/.*)?$/,
38
- /^\.DS_Store$/,
39
- /^\.env$/,
40
- /^bonzai(\/.*)?$/
41
- ];
42
- }
43
-
44
- // Check if a path should be ignored
45
- function shouldIgnore(relativePath, ignorePatterns) {
46
- return ignorePatterns.some(pattern => pattern.test(relativePath));
47
- }
48
-
49
- module.exports = {
50
- getIgnorePatterns,
51
- shouldIgnore
52
- };
53
-