recoder-code 2.2.1 → 2.2.3
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 +9 -7
- package/cli/enhanced-setup.js +3 -1
- package/cli/file-watcher-manager.js +216 -0
- package/cli/interactive.js +1527 -85
- 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
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const readline = require('readline');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const chalkModule = require('chalk');
|
|
7
|
+
const chalk = chalkModule.default || chalkModule;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* User Onboarding for Recoder Code
|
|
11
|
+
* Handles first-time user setup with proper welcome flow
|
|
12
|
+
*/
|
|
13
|
+
class UserOnboarding {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.rl = readline.createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stdout
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
this.configDir = path.join(require('os').homedir(), '.recoder-code');
|
|
21
|
+
this.configFile = path.join(this.configDir, 'config.json');
|
|
22
|
+
this.defaultConfig = {
|
|
23
|
+
apiKey: '',
|
|
24
|
+
model: 'deepseek/deepseek-chat-v3.1:free',
|
|
25
|
+
userName: '',
|
|
26
|
+
setupCompleted: false,
|
|
27
|
+
firstRun: true
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Show ASCII logo and welcome message
|
|
33
|
+
*/
|
|
34
|
+
showWelcome() {
|
|
35
|
+
console.clear();
|
|
36
|
+
console.log(chalk.cyan(`
|
|
37
|
+
██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███████╗██████╗
|
|
38
|
+
██╔══██╗██╔════╝██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗
|
|
39
|
+
██████╔╝█████╗ ██║ ██║ ██║██║ ██║█████╗ ██████╔╝
|
|
40
|
+
██╔══██╗██╔══╝ ██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗
|
|
41
|
+
██║ ██║███████╗╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║
|
|
42
|
+
╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝
|
|
43
|
+
|
|
44
|
+
`));
|
|
45
|
+
|
|
46
|
+
console.log(chalk.white.bold('Welcome to Recoder Code v2.2.3'));
|
|
47
|
+
console.log(chalk.gray('Your AI-powered development companion\n'));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Check if user needs onboarding
|
|
52
|
+
*/
|
|
53
|
+
needsOnboarding() {
|
|
54
|
+
if (!fs.existsSync(this.configFile)) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const config = JSON.parse(fs.readFileSync(this.configFile, 'utf8'));
|
|
60
|
+
return !config.setupCompleted || !config.apiKey;
|
|
61
|
+
} catch (error) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get user's name
|
|
68
|
+
*/
|
|
69
|
+
async getUserName() {
|
|
70
|
+
return new Promise((resolve) => {
|
|
71
|
+
this.rl.question(chalk.cyan('👋 What\'s your name? '), (name) => {
|
|
72
|
+
resolve(name.trim() || 'Developer');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Get API key from user
|
|
79
|
+
*/
|
|
80
|
+
async getApiKey() {
|
|
81
|
+
console.log(chalk.yellow('\n🔑 API Key Setup'));
|
|
82
|
+
console.log(chalk.white('To use Recoder Code, you need an API key from OpenRouter.'));
|
|
83
|
+
console.log(chalk.gray('💡 Get your free API key at: https://openrouter.ai/keys\n'));
|
|
84
|
+
|
|
85
|
+
return new Promise((resolve) => {
|
|
86
|
+
this.rl.question(chalk.cyan('Enter your OpenRouter API key: '), (apiKey) => {
|
|
87
|
+
resolve(apiKey.trim());
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Show model selection
|
|
94
|
+
*/
|
|
95
|
+
async selectModel() {
|
|
96
|
+
console.log(chalk.yellow('\n🤖 Model Selection'));
|
|
97
|
+
console.log(chalk.white('Choose your preferred AI model:'));
|
|
98
|
+
console.log(chalk.gray('1. DeepSeek Chat v3.1 (Free) - Recommended for most users'));
|
|
99
|
+
console.log(chalk.gray('2. Claude 3.5 Sonnet - Advanced reasoning and coding'));
|
|
100
|
+
console.log(chalk.gray('3. GPT-4 Turbo - OpenAI\'s latest model'));
|
|
101
|
+
console.log(chalk.gray('4. Custom model - Enter your own model name\n'));
|
|
102
|
+
|
|
103
|
+
return new Promise((resolve) => {
|
|
104
|
+
this.rl.question(chalk.cyan('Select option (1-4) [1]: '), (choice) => {
|
|
105
|
+
switch (choice.trim() || '1') {
|
|
106
|
+
case '1':
|
|
107
|
+
resolve('deepseek/deepseek-chat-v3.1:free');
|
|
108
|
+
break;
|
|
109
|
+
case '2':
|
|
110
|
+
resolve('anthropic/claude-3.5-sonnet');
|
|
111
|
+
break;
|
|
112
|
+
case '3':
|
|
113
|
+
resolve('openai/gpt-4-turbo');
|
|
114
|
+
break;
|
|
115
|
+
case '4':
|
|
116
|
+
this.rl.question(chalk.cyan('Enter custom model name: '), (customModel) => {
|
|
117
|
+
resolve(customModel.trim() || 'deepseek/deepseek-chat-v3.1:free');
|
|
118
|
+
});
|
|
119
|
+
break;
|
|
120
|
+
default:
|
|
121
|
+
resolve('deepseek/deepseek-chat-v3.1:free');
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Save configuration
|
|
129
|
+
*/
|
|
130
|
+
saveConfig(config) {
|
|
131
|
+
try {
|
|
132
|
+
// Create config directory if it doesn't exist
|
|
133
|
+
if (!fs.existsSync(this.configDir)) {
|
|
134
|
+
fs.mkdirSync(this.configDir, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Save configuration
|
|
138
|
+
fs.writeFileSync(this.configFile, JSON.stringify(config, null, 2));
|
|
139
|
+
return true;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.log(chalk.red(`❌ Failed to save configuration: ${error.message}`));
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Load existing configuration
|
|
148
|
+
*/
|
|
149
|
+
loadConfig() {
|
|
150
|
+
try {
|
|
151
|
+
if (fs.existsSync(this.configFile)) {
|
|
152
|
+
return JSON.parse(fs.readFileSync(this.configFile, 'utf8'));
|
|
153
|
+
}
|
|
154
|
+
} catch (error) {
|
|
155
|
+
// Return default if config can't be loaded
|
|
156
|
+
}
|
|
157
|
+
return { ...this.defaultConfig };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Show setup completion
|
|
162
|
+
*/
|
|
163
|
+
showCompletion(userName, model) {
|
|
164
|
+
console.log(chalk.green('\n✅ Setup Complete!'));
|
|
165
|
+
console.log(chalk.white(`Welcome aboard, ${userName}! 🎉`));
|
|
166
|
+
console.log(chalk.gray(`Model: ${model}`));
|
|
167
|
+
console.log(chalk.gray('Configuration saved to ~/.recoder-code/config.json\n'));
|
|
168
|
+
|
|
169
|
+
console.log(chalk.cyan('🚀 Quick Start:'));
|
|
170
|
+
console.log(chalk.white('• Type your questions or requests'));
|
|
171
|
+
console.log(chalk.white('• Use /help for available commands'));
|
|
172
|
+
console.log(chalk.white('• Press Ctrl+C to exit anytime\n'));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Run complete onboarding flow
|
|
177
|
+
*/
|
|
178
|
+
async runOnboarding() {
|
|
179
|
+
this.showWelcome();
|
|
180
|
+
|
|
181
|
+
const userName = await this.getUserName();
|
|
182
|
+
const apiKey = await this.getApiKey();
|
|
183
|
+
|
|
184
|
+
if (!apiKey) {
|
|
185
|
+
console.log(chalk.red('\n❌ API key is required to use Recoder Code.'));
|
|
186
|
+
console.log(chalk.yellow('Get your free key at: https://openrouter.ai/keys'));
|
|
187
|
+
this.rl.close();
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const model = await this.selectModel();
|
|
192
|
+
|
|
193
|
+
const config = {
|
|
194
|
+
...this.defaultConfig,
|
|
195
|
+
apiKey,
|
|
196
|
+
model,
|
|
197
|
+
userName,
|
|
198
|
+
setupCompleted: true,
|
|
199
|
+
firstRun: false,
|
|
200
|
+
setupDate: new Date().toISOString()
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
if (this.saveConfig(config)) {
|
|
204
|
+
this.showCompletion(userName, model);
|
|
205
|
+
} else {
|
|
206
|
+
console.log(chalk.red('\n❌ Setup failed. Please try again.'));
|
|
207
|
+
this.rl.close();
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Set environment variables for immediate use
|
|
212
|
+
process.env.OPENROUTER_API_KEY = config.apiKey;
|
|
213
|
+
process.env.OPENROUTER_MODEL = config.model;
|
|
214
|
+
process.env.RECODER_USER_MODE = 'true'; // Suppress technical messages
|
|
215
|
+
|
|
216
|
+
this.rl.close();
|
|
217
|
+
return config;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Quick start for returning users
|
|
222
|
+
*/
|
|
223
|
+
async quickStart() {
|
|
224
|
+
const config = this.loadConfig();
|
|
225
|
+
|
|
226
|
+
if (!config.setupCompleted || !config.apiKey) {
|
|
227
|
+
return await this.runOnboarding();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Show welcome for returning users
|
|
231
|
+
this.showWelcome();
|
|
232
|
+
console.log(chalk.green(`Welcome back, ${config.userName || 'Developer'}! 👋`));
|
|
233
|
+
console.log(chalk.gray(`Using model: ${config.model}\n`));
|
|
234
|
+
|
|
235
|
+
// Set environment variables for immediate use
|
|
236
|
+
process.env.OPENROUTER_API_KEY = config.apiKey;
|
|
237
|
+
process.env.OPENROUTER_MODEL = config.model;
|
|
238
|
+
process.env.RECODER_USER_MODE = 'true'; // Suppress technical messages
|
|
239
|
+
|
|
240
|
+
return config;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Close readline interface
|
|
245
|
+
*/
|
|
246
|
+
close() {
|
|
247
|
+
this.rl.close();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
module.exports = UserOnboarding;
|
package/cli/vision-analyzer.js
CHANGED
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Recoder Code - AI Development Platform
|
|
4
|
-
*
|
|
4
|
+
* Production-ready main entry point for programmatic usage
|
|
5
5
|
*
|
|
6
6
|
* For CLI usage: Use `recoder-code` command
|
|
7
7
|
* For programmatic usage: require('recoder-code')
|
|
@@ -10,6 +10,19 @@
|
|
|
10
10
|
const path = require('path');
|
|
11
11
|
const config = require('./config.js');
|
|
12
12
|
|
|
13
|
+
// Handle chalk properly for production
|
|
14
|
+
const chalkModule = require('chalk');
|
|
15
|
+
const chalk = chalkModule.default || chalkModule;
|
|
16
|
+
|
|
17
|
+
// Initialize unified error handling
|
|
18
|
+
const UnifiedErrorHandler = require('./cli/unified-error-handler.js');
|
|
19
|
+
const errorHandler = UnifiedErrorHandler.instance;
|
|
20
|
+
|
|
21
|
+
// Only initialize in non-test environments
|
|
22
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
23
|
+
errorHandler.initialize();
|
|
24
|
+
}
|
|
25
|
+
|
|
13
26
|
// Main RecoderCode class for programmatic usage
|
|
14
27
|
class RecoderCode {
|
|
15
28
|
constructor(options = {}) {
|
|
@@ -82,22 +95,81 @@ class RecoderCode {
|
|
|
82
95
|
const discovery = new ProgressiveDiscovery();
|
|
83
96
|
return discovery.getProgressSummary();
|
|
84
97
|
}
|
|
98
|
+
|
|
99
|
+
// Todo management
|
|
100
|
+
async getTodoManager() {
|
|
101
|
+
const TodoManager = require('./cli/todo-manager.js');
|
|
102
|
+
return new TodoManager({ user: this.currentUser || 'developer' });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Production health check
|
|
106
|
+
async healthCheck() {
|
|
107
|
+
const checks = {
|
|
108
|
+
dependencies: false,
|
|
109
|
+
configuration: false,
|
|
110
|
+
services: false,
|
|
111
|
+
todos: false
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
// Check dependencies
|
|
116
|
+
require('chalk');
|
|
117
|
+
require('openai');
|
|
118
|
+
checks.dependencies = true;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('Dependency check failed:', error.message);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
// Check configuration
|
|
125
|
+
const config = require('./config.js');
|
|
126
|
+
checks.configuration = !!config;
|
|
127
|
+
} catch (error) {
|
|
128
|
+
console.error('Configuration check failed:', error.message);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
// Check services
|
|
133
|
+
const status = await this.getServicesStatus();
|
|
134
|
+
checks.services = true;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error('Services check failed:', error.message);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
// Check todo system
|
|
141
|
+
const todoManager = await this.getTodoManager();
|
|
142
|
+
checks.todos = true;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
console.error('Todo system check failed:', error.message);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return checks;
|
|
148
|
+
}
|
|
85
149
|
}
|
|
86
150
|
|
|
87
151
|
// Legacy compatibility - simple OpenAI client function
|
|
88
152
|
async function legacyMain() {
|
|
89
|
-
const OpenAI = require('openai');
|
|
90
|
-
|
|
91
|
-
const openai = new OpenAI({
|
|
92
|
-
baseURL: config.apiUrl,
|
|
93
|
-
apiKey: config.openRouterApiKey,
|
|
94
|
-
defaultHeaders: {
|
|
95
|
-
'HTTP-Referer': config.siteUrl || 'https://recoder.xyz',
|
|
96
|
-
'X-Title': config.siteName || 'Recoder-Code',
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
|
|
100
153
|
try {
|
|
154
|
+
// Check if API key is configured
|
|
155
|
+
if (!config.openRouterApiKey) {
|
|
156
|
+
console.log(chalk.yellow('⚠️ No API key configured.'));
|
|
157
|
+
console.log(chalk.white('To configure: export OPENROUTER_API_KEY="your-key"'));
|
|
158
|
+
console.log(chalk.white('Or run: recoder-code setup'));
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const OpenAI = require('openai');
|
|
163
|
+
|
|
164
|
+
const openai = new OpenAI({
|
|
165
|
+
baseURL: config.apiUrl,
|
|
166
|
+
apiKey: config.openRouterApiKey,
|
|
167
|
+
defaultHeaders: {
|
|
168
|
+
'HTTP-Referer': config.siteUrl || 'https://recoder.xyz',
|
|
169
|
+
'X-Title': config.siteName || 'Recoder-Code',
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
|
|
101
173
|
const completion = await openai.chat.completions.create({
|
|
102
174
|
model: config.model || 'deepseek/deepseek-chat',
|
|
103
175
|
messages: [
|
|
@@ -110,7 +182,10 @@ async function legacyMain() {
|
|
|
110
182
|
|
|
111
183
|
console.log(completion.choices[0].message.content);
|
|
112
184
|
} catch (error) {
|
|
113
|
-
console.error('API request failed:', error.message);
|
|
185
|
+
console.error(chalk.red('❌ API request failed:'), error.message);
|
|
186
|
+
if (error.message.includes('credentials') || error.message.includes('apiKey')) {
|
|
187
|
+
console.log(chalk.yellow('💡 Tip: Set your API key with: export OPENROUTER_API_KEY="your-key"'));
|
|
188
|
+
}
|
|
114
189
|
}
|
|
115
190
|
}
|
|
116
191
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "recoder-code",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.3",
|
|
4
4
|
"description": "Complete AI-powered development platform with ML model training, plugin registry, real-time collaboration, monitoring, infrastructure automation, and enterprise deployment capabilities",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -28,6 +28,12 @@
|
|
|
28
28
|
"security:audit": "npm audit --audit-level moderate",
|
|
29
29
|
"optimize": "node scripts/optimize-package.js",
|
|
30
30
|
"health-check": "node scripts/health-check.js",
|
|
31
|
+
"todo": "node cli/todo-manager.js",
|
|
32
|
+
"todo:list": "node cli/todo-manager.js list",
|
|
33
|
+
"todo:stats": "node cli/todo-manager.js stats",
|
|
34
|
+
"production:check": "npm run test && npm run lint && npm run typecheck && npm run security:audit",
|
|
35
|
+
"production:bundle": "npm run production:check && npm run build:production",
|
|
36
|
+
"production:deploy": "npm run production:bundle && npm publish --access public",
|
|
31
37
|
"postinstall": "node -e \"console.log('\\n🚀 Recoder-Code installed successfully!\\n\\n✅ Quick Start:\\n recoder-code\\n\\n💡 If command not found, run setup:\\n npx recoder-code setup:global\\n\\nOr add npm global bin to PATH manually:\\n echo \\\"export PATH=\\\\\\\"$(npm config get prefix)/bin:$PATH\\\\\\\"\\\" >> ~/.zshrc\\n source ~/.zshrc\\n\\n🎉 Then try: recoder-code --help\\n')\"",
|
|
32
38
|
"prepare": "echo 'Package prepared for distribution'",
|
|
33
39
|
"prepublishOnly": "npm run prepare && npm run security:audit"
|
|
@@ -57,21 +57,41 @@ class EnhancedPluginManager {
|
|
|
57
57
|
filename: filename,
|
|
58
58
|
enabled: pluginModule.enabled !== false,
|
|
59
59
|
|
|
60
|
-
// Plugin functions
|
|
61
|
-
init: pluginModule.init
|
|
62
|
-
cleanup: pluginModule.cleanup
|
|
63
|
-
onMessage: pluginModule.onMessage
|
|
64
|
-
onResponse: pluginModule.onResponse
|
|
65
|
-
onCommand: pluginModule.onCommand
|
|
66
|
-
onFileChange: pluginModule.onFileChange
|
|
60
|
+
// Plugin functions - bind to original module context
|
|
61
|
+
init: pluginModule.init ? pluginModule.init.bind(pluginModule) : (() => {}),
|
|
62
|
+
cleanup: pluginModule.cleanup ? pluginModule.cleanup.bind(pluginModule) : (() => {}),
|
|
63
|
+
onMessage: pluginModule.onMessage ? pluginModule.onMessage.bind(pluginModule) : null,
|
|
64
|
+
onResponse: pluginModule.onResponse ? pluginModule.onResponse.bind(pluginModule) : null,
|
|
65
|
+
onCommand: pluginModule.onCommand ? pluginModule.onCommand.bind(pluginModule) : null,
|
|
66
|
+
onFileChange: pluginModule.onFileChange ? pluginModule.onFileChange.bind(pluginModule) : null,
|
|
67
67
|
|
|
68
|
-
//
|
|
69
|
-
|
|
68
|
+
// Store reference to original module for context
|
|
69
|
+
module: pluginModule,
|
|
70
70
|
|
|
71
|
-
//
|
|
72
|
-
|
|
71
|
+
// Custom commands - bind each command handler
|
|
72
|
+
commands: {},
|
|
73
|
+
|
|
74
|
+
// Hooks - bind each hook handler
|
|
75
|
+
hooks: {}
|
|
73
76
|
};
|
|
74
77
|
|
|
78
|
+
// Bind ALL methods of the plugin module to preserve context
|
|
79
|
+
Object.getOwnPropertyNames(pluginModule).forEach(prop => {
|
|
80
|
+
if (typeof pluginModule[prop] === 'function' && !plugin.hasOwnProperty(prop)) {
|
|
81
|
+
plugin[prop] = pluginModule[prop].bind(pluginModule);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Bind command handlers to original module context
|
|
86
|
+
Object.entries(pluginModule.commands || {}).forEach(([command, handler]) => {
|
|
87
|
+
plugin.commands[command] = typeof handler === 'function' ? handler.bind(pluginModule) : handler;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Bind hook handlers to original module context
|
|
91
|
+
Object.entries(pluginModule.hooks || {}).forEach(([hook, handler]) => {
|
|
92
|
+
plugin.hooks[hook] = typeof handler === 'function' ? handler.bind(pluginModule) : handler;
|
|
93
|
+
});
|
|
94
|
+
|
|
75
95
|
// Register plugin
|
|
76
96
|
this.plugins.set(plugin.name, plugin);
|
|
77
97
|
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const { execSync, spawn } = require('child_process');
|
|
11
|
-
|
|
11
|
+
// Handle chalk properly
|
|
12
|
+
const chalkModule = require('chalk');
|
|
13
|
+
const chalk = chalkModule.default || chalkModule;
|
|
12
14
|
const { performance } = require('perf_hooks');
|
|
13
15
|
|
|
14
16
|
class PerformanceBenchmark {
|
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const { execSync } = require('child_process');
|
|
11
|
-
|
|
11
|
+
// Handle chalk properly
|
|
12
|
+
const chalkModule = require('chalk');
|
|
13
|
+
const chalk = chalkModule.default || chalkModule;
|
|
12
14
|
|
|
13
15
|
class SecurityAuditor {
|
|
14
16
|
constructor() {
|
package/setup.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const readline = require('readline');
|
|
6
|
-
|
|
6
|
+
// Handle chalk properly
|
|
7
|
+
const chalkModule = require('chalk');
|
|
8
|
+
const chalk = chalkModule.default || chalkModule;
|
|
7
9
|
const { exec } = require('child_process');
|
|
8
10
|
const { promisify } = require('util');
|
|
9
11
|
|