recoder-code 2.2.1 → 2.2.2
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/README.md +66 -10
- package/cli/collaboration-manager.js +3 -1
- package/cli/dev-tools-integration.js +3 -1
- package/cli/enhanced-setup.js +3 -1
- package/cli/file-watcher-manager.js +216 -0
- package/cli/interactive.js +1476 -62
- package/cli/logger.js +181 -0
- package/cli/mcp-client.js +32 -9
- package/cli/ml-training-manager.js +3 -1
- package/cli/natural-language-processor.js +3 -1
- package/cli/project-manager.js +3 -1
- package/cli/rules-engine.js +9 -4
- package/cli/run.js +90 -13
- package/cli/setup-wizard.js +3 -1
- package/cli/slash-commands.js +132 -5
- package/cli/task-manager.js +13 -5
- package/cli/team-collaboration.js +3 -1
- package/cli/todo-manager.js +391 -0
- package/cli/unified-error-handler.js +260 -0
- package/cli/user-experience.js +3 -1
- package/cli/user-onboarding.js +251 -0
- package/cli/vision-analyzer.js +3 -1
- package/index.js +88 -13
- package/package.json +7 -1
- package/plugins/enhanced-plugin-manager.js +31 -11
- package/scripts/performance-benchmark.js +3 -1
- package/scripts/security-audit.js +3 -1
- package/setup.js +3 -1
package/README.md
CHANGED
|
@@ -30,20 +30,65 @@
|
|
|
30
30
|
|
|
31
31
|
## 🚀 Quick Start
|
|
32
32
|
|
|
33
|
-
###
|
|
33
|
+
### Perfect Production-Ready User Flow
|
|
34
|
+
|
|
35
|
+
**⚠️ Important:** Use `npm install -g` (not `npm i` shown on some npm pages) for global installation.
|
|
34
36
|
|
|
35
37
|
```bash
|
|
36
|
-
# Install globally
|
|
38
|
+
# 1. Install globally (use full command for global install)
|
|
37
39
|
npm install -g recoder-code
|
|
38
40
|
|
|
39
|
-
#
|
|
40
|
-
recoder-code
|
|
41
|
+
# 2. Launch Recoder Code
|
|
42
|
+
recoder-code
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**That's it!** When you run `recoder-code`, you'll see:
|
|
46
|
+
|
|
47
|
+
1. **🎨 Beautiful ASCII Logo** - Professional welcome screen
|
|
48
|
+
2. **👋 Personal Setup** - Enter your name and get your free API key
|
|
49
|
+
3. **🤖 Model Selection** - Choose your AI model (defaults to free DeepSeek)
|
|
50
|
+
4. **🚀 Ready to Code** - Interactive AI terminal launches instantly
|
|
41
51
|
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
### ✨ First-Time User Experience
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗
|
|
56
|
+
██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗
|
|
57
|
+
██████╔╝█████╗ ██║ ██║ ██║██║ ██║█████╗ ██████╔╝
|
|
58
|
+
██╔══██╗██╔══╝ ██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗
|
|
59
|
+
██║ ██║███████╗╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║
|
|
60
|
+
╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
|
|
61
|
+
|
|
62
|
+
Welcome to Recoder Code v2.2.2
|
|
63
|
+
Your AI-powered development companion
|
|
64
|
+
|
|
65
|
+
👋 What's your name? John
|
|
66
|
+
🔑 Enter your OpenRouter API key: [your-free-key]
|
|
67
|
+
🤖 Model Selection:
|
|
68
|
+
1. DeepSeek Chat v3.1 (Free) - Recommended ✨
|
|
69
|
+
2. Claude 3.5 Sonnet - Advanced reasoning
|
|
70
|
+
3. GPT-4 Turbo - OpenAI's latest
|
|
71
|
+
4. Custom model
|
|
72
|
+
|
|
73
|
+
✅ Setup Complete! Welcome aboard, John! 🎉
|
|
74
|
+
Ready for AI-powered development...
|
|
44
75
|
```
|
|
45
76
|
|
|
46
|
-
|
|
77
|
+
### 🔄 Returning Users
|
|
78
|
+
|
|
79
|
+
For returning users, just run `recoder-code` and you'll get:
|
|
80
|
+
- Instant welcome back with your saved preferences
|
|
81
|
+
- No setup required - jumps straight to AI chat
|
|
82
|
+
- Your chosen model and settings remembered
|
|
83
|
+
|
|
84
|
+
### 🆓 Free API Key Setup
|
|
85
|
+
|
|
86
|
+
1. Visit [OpenRouter.ai](https://openrouter.ai/keys)
|
|
87
|
+
2. Sign up for free account
|
|
88
|
+
3. Generate your API key
|
|
89
|
+
4. Paste when prompted during setup
|
|
90
|
+
|
|
91
|
+
**Default Model:** `deepseek/deepseek-chat-v3.1:free` - Completely free, no subscription needed!
|
|
47
92
|
|
|
48
93
|
### All Available Commands
|
|
49
94
|
|
|
@@ -152,10 +197,17 @@ Recoder-Code automatically suggests new features as you become ready:
|
|
|
152
197
|
|
|
153
198
|
## 🛠️ Installation & Setup Options
|
|
154
199
|
|
|
200
|
+
> **⚠️ NPM Command Important Notice**
|
|
201
|
+
> Always use `npm install -g recoder-code` (full command) for global installation.
|
|
202
|
+
> The `npm i` shorthand shown on some npm websites is incorrect for global installs and may cause issues.
|
|
203
|
+
|
|
155
204
|
### Option 1: NPM Global Install (Recommended)
|
|
156
205
|
```bash
|
|
206
|
+
# Use full command for global install (not npm i)
|
|
157
207
|
npm install -g recoder-code
|
|
158
|
-
|
|
208
|
+
|
|
209
|
+
# Launch with onboarding
|
|
210
|
+
recoder-code
|
|
159
211
|
```
|
|
160
212
|
|
|
161
213
|
### Option 2: From Source
|
|
@@ -360,9 +412,13 @@ MIT License - see [LICENSE.md](LICENSE.md) for details.
|
|
|
360
412
|
**Ready to transform your development workflow?**
|
|
361
413
|
|
|
362
414
|
```bash
|
|
415
|
+
# Install globally (use full command, not npm i)
|
|
363
416
|
npm install -g recoder-code
|
|
364
|
-
|
|
365
|
-
|
|
417
|
+
|
|
418
|
+
# Launch with beautiful onboarding
|
|
419
|
+
recoder-code
|
|
420
|
+
|
|
421
|
+
# Start building amazing things!
|
|
366
422
|
```
|
|
367
423
|
|
|
368
424
|
*The AI development platform that grows with you.* 🚀
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
|
|
3
|
+
// Handle chalk properly
|
|
4
|
+
const chalkModule = require('chalk');
|
|
5
|
+
const chalk = chalkModule.default || chalkModule;
|
|
4
6
|
const crypto = require('crypto');
|
|
5
7
|
|
|
6
8
|
class CollaborationManager {
|
|
@@ -4,7 +4,9 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const { exec, spawn } = require('child_process');
|
|
6
6
|
const { promisify } = require('util');
|
|
7
|
-
|
|
7
|
+
// Handle chalk properly
|
|
8
|
+
const chalkModule = require('chalk');
|
|
9
|
+
const chalk = chalkModule.default || chalkModule;
|
|
8
10
|
const { EventEmitter } = require('events');
|
|
9
11
|
|
|
10
12
|
const execAsync = promisify(exec);
|
package/cli/enhanced-setup.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const inquirer = require('inquirer');
|
|
4
|
-
|
|
4
|
+
// Handle chalk properly
|
|
5
|
+
const chalkModule = require('chalk');
|
|
6
|
+
const chalk = chalkModule.default || chalkModule;;
|
|
5
7
|
const fs = require('fs');
|
|
6
8
|
const path = require('path');
|
|
7
9
|
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const chokidar = require('chokidar');
|
|
4
|
+
const chalkModule = require('chalk');
|
|
5
|
+
const chalk = chalkModule.default || chalkModule;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* File Watcher Resource Manager
|
|
9
|
+
* Prevents EMFILE errors by managing file watchers globally
|
|
10
|
+
*/
|
|
11
|
+
class FileWatcherManager {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.watchers = new Map();
|
|
14
|
+
this.watchTargets = new Map(); // Track what's being watched
|
|
15
|
+
this.maxWatchers = 50; // Conservative limit
|
|
16
|
+
this.isShuttingDown = false;
|
|
17
|
+
|
|
18
|
+
// Global cleanup on process exit
|
|
19
|
+
process.on('exit', () => this.cleanup());
|
|
20
|
+
process.on('SIGINT', () => this.cleanup());
|
|
21
|
+
process.on('SIGTERM', () => this.cleanup());
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Create or reuse a file watcher
|
|
26
|
+
*/
|
|
27
|
+
createWatcher(id, paths, options = {}, callbacks = {}) {
|
|
28
|
+
// If we already have a watcher for this ID, clean it up first
|
|
29
|
+
if (this.watchers.has(id)) {
|
|
30
|
+
this.removeWatcher(id);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check watcher limit
|
|
34
|
+
if (this.watchers.size >= this.maxWatchers) {
|
|
35
|
+
console.log(chalk.yellow(`⚠️ File watcher limit reached (${this.maxWatchers}), skipping ${id}`));
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
// Create watcher with safe defaults
|
|
41
|
+
const safeOptions = {
|
|
42
|
+
persistent: false, // Don't keep process alive
|
|
43
|
+
ignoreInitial: true,
|
|
44
|
+
usePolling: false,
|
|
45
|
+
ignorePermissionErrors: true,
|
|
46
|
+
...options
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const watcher = chokidar.watch(paths, safeOptions);
|
|
50
|
+
|
|
51
|
+
// Set up callbacks
|
|
52
|
+
if (callbacks.onChange) {
|
|
53
|
+
watcher.on('change', (path) => {
|
|
54
|
+
try {
|
|
55
|
+
callbacks.onChange(path);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
58
|
+
console.log(chalk.gray(`📁 File watcher ${id} change error:`, error.message));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (callbacks.onAdd) {
|
|
65
|
+
watcher.on('add', (path) => {
|
|
66
|
+
try {
|
|
67
|
+
callbacks.onAdd(path);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
70
|
+
console.log(chalk.gray(`📁 File watcher ${id} add error:`, error.message));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (callbacks.onUnlink) {
|
|
77
|
+
watcher.on('unlink', (path) => {
|
|
78
|
+
try {
|
|
79
|
+
callbacks.onUnlink(path);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
82
|
+
console.log(chalk.gray(`📁 File watcher ${id} unlink error:`, error.message));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Handle watcher errors gracefully
|
|
89
|
+
watcher.on('error', (error) => {
|
|
90
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
91
|
+
console.log(chalk.gray(`📁 File watcher ${id} error:`, error.message));
|
|
92
|
+
}
|
|
93
|
+
// Auto-remove problematic watchers
|
|
94
|
+
this.removeWatcher(id);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Store watcher
|
|
98
|
+
this.watchers.set(id, watcher);
|
|
99
|
+
this.watchTargets.set(id, { paths, options, callbacks });
|
|
100
|
+
|
|
101
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
102
|
+
console.log(chalk.gray(`📁 File watcher ${id} created (total: ${this.watchers.size})`));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return watcher;
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.log(chalk.yellow(`⚠️ Failed to create file watcher ${id}:`, error.message));
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Remove a specific watcher
|
|
114
|
+
*/
|
|
115
|
+
removeWatcher(id) {
|
|
116
|
+
const watcher = this.watchers.get(id);
|
|
117
|
+
if (watcher) {
|
|
118
|
+
try {
|
|
119
|
+
watcher.close();
|
|
120
|
+
} catch (error) {
|
|
121
|
+
// Ignore cleanup errors
|
|
122
|
+
}
|
|
123
|
+
this.watchers.delete(id);
|
|
124
|
+
this.watchTargets.delete(id);
|
|
125
|
+
|
|
126
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
127
|
+
console.log(chalk.gray(`📁 File watcher ${id} removed (total: ${this.watchers.size})`));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Get watcher by ID
|
|
134
|
+
*/
|
|
135
|
+
getWatcher(id) {
|
|
136
|
+
return this.watchers.get(id);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Check if watcher exists
|
|
141
|
+
*/
|
|
142
|
+
hasWatcher(id) {
|
|
143
|
+
return this.watchers.has(id);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Get watcher count
|
|
148
|
+
*/
|
|
149
|
+
getWatcherCount() {
|
|
150
|
+
return this.watchers.size;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* List all active watchers
|
|
155
|
+
*/
|
|
156
|
+
listWatchers() {
|
|
157
|
+
return Array.from(this.watchers.keys());
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Cleanup all watchers
|
|
162
|
+
*/
|
|
163
|
+
cleanup() {
|
|
164
|
+
if (this.isShuttingDown) return;
|
|
165
|
+
this.isShuttingDown = true;
|
|
166
|
+
|
|
167
|
+
console.log(chalk.gray(`📁 Cleaning up ${this.watchers.size} file watchers...`));
|
|
168
|
+
|
|
169
|
+
for (const [id, watcher] of this.watchers) {
|
|
170
|
+
try {
|
|
171
|
+
watcher.close();
|
|
172
|
+
} catch (error) {
|
|
173
|
+
// Ignore cleanup errors
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
this.watchers.clear();
|
|
178
|
+
this.watchTargets.clear();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Health check - remove dead watchers
|
|
183
|
+
*/
|
|
184
|
+
healthCheck() {
|
|
185
|
+
const deadWatchers = [];
|
|
186
|
+
|
|
187
|
+
for (const [id, watcher] of this.watchers) {
|
|
188
|
+
try {
|
|
189
|
+
// Try to get watched paths - if this fails, watcher is dead
|
|
190
|
+
if (!watcher.getWatched || Object.keys(watcher.getWatched()).length === 0) {
|
|
191
|
+
deadWatchers.push(id);
|
|
192
|
+
}
|
|
193
|
+
} catch (error) {
|
|
194
|
+
deadWatchers.push(id);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Remove dead watchers
|
|
199
|
+
deadWatchers.forEach(id => this.removeWatcher(id));
|
|
200
|
+
|
|
201
|
+
if (deadWatchers.length > 0 && process.env.RECODER_DEBUG === 'true') {
|
|
202
|
+
console.log(chalk.gray(`📁 Removed ${deadWatchers.length} dead file watchers`));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Global singleton instance
|
|
208
|
+
const fileWatcherManager = new FileWatcherManager();
|
|
209
|
+
|
|
210
|
+
// Periodic health check
|
|
211
|
+
setInterval(() => {
|
|
212
|
+
fileWatcherManager.healthCheck();
|
|
213
|
+
}, 30000); // Every 30 seconds
|
|
214
|
+
|
|
215
|
+
module.exports = FileWatcherManager;
|
|
216
|
+
module.exports.instance = fileWatcherManager;
|