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.
@@ -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;
@@ -2,7 +2,9 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const chalk = require('chalk');
5
+ // Handle chalk properly
6
+ const chalkModule = require('chalk');
7
+ const chalk = chalkModule.default || chalkModule;
6
8
 
7
9
  /**
8
10
  * Vision Analysis Engine
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Recoder Code - AI Development Platform
4
- * Main entry point for programmatic usage
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.1",
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 || null,
64
- onResponse: pluginModule.onResponse || null,
65
- onCommand: pluginModule.onCommand || null,
66
- onFileChange: pluginModule.onFileChange || null,
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
- // Custom commands
69
- commands: pluginModule.commands || {},
68
+ // Store reference to original module for context
69
+ module: pluginModule,
70
70
 
71
- // Hooks
72
- hooks: pluginModule.hooks || {}
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
- const chalk = require('chalk');
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
- const chalk = require('chalk');
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
- const chalk = require('chalk');
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