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/cli/logger.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const chalkModule = require('chalk');
|
|
6
|
+
const chalk = chalkModule.default || chalkModule;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Production Logger for Recoder Code
|
|
10
|
+
* Handles different log levels and environments
|
|
11
|
+
*/
|
|
12
|
+
class Logger {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.logLevel = options.logLevel || process.env.LOG_LEVEL || 'info';
|
|
15
|
+
this.silent = options.silent || process.env.RECODER_SILENT === 'true';
|
|
16
|
+
this.logFile = options.logFile || path.join(process.cwd(), 'logs', 'recoder.log');
|
|
17
|
+
this.enableFileLogging = options.enableFileLogging !== false;
|
|
18
|
+
|
|
19
|
+
// Create logs directory
|
|
20
|
+
if (this.enableFileLogging) {
|
|
21
|
+
const logDir = path.dirname(this.logFile);
|
|
22
|
+
if (!fs.existsSync(logDir)) {
|
|
23
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
this.levels = {
|
|
28
|
+
error: 0,
|
|
29
|
+
warn: 1,
|
|
30
|
+
info: 2,
|
|
31
|
+
debug: 3
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_shouldLog(level) {
|
|
36
|
+
return this.levels[level] <= this.levels[this.logLevel];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
_formatMessage(level, message, ...args) {
|
|
40
|
+
const timestamp = new Date().toISOString();
|
|
41
|
+
const formattedArgs = args.map(arg =>
|
|
42
|
+
typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
|
|
43
|
+
).join(' ');
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
console: this._colorizeMessage(level, message, formattedArgs),
|
|
47
|
+
file: `[${timestamp}] ${level.toUpperCase()}: ${message} ${formattedArgs}`.trim()
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
_colorizeMessage(level, message, args) {
|
|
52
|
+
const fullMessage = `${message} ${args}`.trim();
|
|
53
|
+
|
|
54
|
+
switch (level) {
|
|
55
|
+
case 'error':
|
|
56
|
+
return chalk.red(`❌ ${fullMessage}`);
|
|
57
|
+
case 'warn':
|
|
58
|
+
return chalk.yellow(`⚠️ ${fullMessage}`);
|
|
59
|
+
case 'info':
|
|
60
|
+
return chalk.blue(`ℹ️ ${fullMessage}`);
|
|
61
|
+
case 'debug':
|
|
62
|
+
return chalk.gray(`🔍 ${fullMessage}`);
|
|
63
|
+
default:
|
|
64
|
+
return fullMessage;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_writeToFile(message) {
|
|
69
|
+
if (this.enableFileLogging) {
|
|
70
|
+
try {
|
|
71
|
+
fs.appendFileSync(this.logFile, message + '\n');
|
|
72
|
+
} catch (error) {
|
|
73
|
+
// Fail silently for file logging errors
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
error(message, ...args) {
|
|
79
|
+
if (this._shouldLog('error')) {
|
|
80
|
+
const formatted = this._formatMessage('error', message, ...args);
|
|
81
|
+
if (!this.silent) {
|
|
82
|
+
console.error(formatted.console);
|
|
83
|
+
}
|
|
84
|
+
this._writeToFile(formatted.file);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
warn(message, ...args) {
|
|
89
|
+
if (this._shouldLog('warn')) {
|
|
90
|
+
const formatted = this._formatMessage('warn', message, ...args);
|
|
91
|
+
if (!this.silent) {
|
|
92
|
+
console.warn(formatted.console);
|
|
93
|
+
}
|
|
94
|
+
this._writeToFile(formatted.file);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
info(message, ...args) {
|
|
99
|
+
if (this._shouldLog('info')) {
|
|
100
|
+
const formatted = this._formatMessage('info', message, ...args);
|
|
101
|
+
if (!this.silent) {
|
|
102
|
+
console.log(formatted.console);
|
|
103
|
+
}
|
|
104
|
+
this._writeToFile(formatted.file);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
debug(message, ...args) {
|
|
109
|
+
if (this._shouldLog('debug')) {
|
|
110
|
+
const formatted = this._formatMessage('debug', message, ...args);
|
|
111
|
+
if (!this.silent) {
|
|
112
|
+
console.log(formatted.console);
|
|
113
|
+
}
|
|
114
|
+
this._writeToFile(formatted.file);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Production-safe console.log replacement
|
|
119
|
+
log(message, ...args) {
|
|
120
|
+
// In production, treat as info level
|
|
121
|
+
if (process.env.NODE_ENV === 'production') {
|
|
122
|
+
this.info(message, ...args);
|
|
123
|
+
} else {
|
|
124
|
+
// In development, allow direct logging
|
|
125
|
+
console.log(message, ...args);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Success messages for user feedback
|
|
130
|
+
success(message, ...args) {
|
|
131
|
+
const formatted = `✅ ${message} ${args.join(' ')}`.trim();
|
|
132
|
+
if (!this.silent) {
|
|
133
|
+
console.log(chalk.green(formatted));
|
|
134
|
+
}
|
|
135
|
+
this._writeToFile(`[${new Date().toISOString()}] SUCCESS: ${message} ${args.join(' ')}`.trim());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Progress indicators
|
|
139
|
+
progress(message, ...args) {
|
|
140
|
+
const formatted = `⏳ ${message} ${args.join(' ')}`.trim();
|
|
141
|
+
if (!this.silent) {
|
|
142
|
+
console.log(chalk.cyan(formatted));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// User prompts and interactive messages
|
|
147
|
+
user(message, ...args) {
|
|
148
|
+
const formatted = `${message} ${args.join(' ')}`.trim();
|
|
149
|
+
if (!this.silent) {
|
|
150
|
+
console.log(formatted);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Global logger instance
|
|
156
|
+
const logger = new Logger();
|
|
157
|
+
|
|
158
|
+
// Replace console methods in production
|
|
159
|
+
if (process.env.NODE_ENV === 'production') {
|
|
160
|
+
// Store original methods
|
|
161
|
+
const originalConsole = {
|
|
162
|
+
log: console.log,
|
|
163
|
+
error: console.error,
|
|
164
|
+
warn: console.warn,
|
|
165
|
+
info: console.info
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Override console methods
|
|
169
|
+
console.log = (...args) => logger.log(...args);
|
|
170
|
+
console.error = (...args) => logger.error(...args);
|
|
171
|
+
console.warn = (...args) => logger.warn(...args);
|
|
172
|
+
console.info = (...args) => logger.info(...args);
|
|
173
|
+
|
|
174
|
+
// Provide way to restore original console
|
|
175
|
+
console._restore = () => {
|
|
176
|
+
Object.assign(console, originalConsole);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = Logger;
|
|
181
|
+
module.exports.logger = logger;
|
package/cli/mcp-client.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
|
|
5
|
+
// Handle chalk properly
|
|
6
|
+
const chalkModule = require('chalk');
|
|
7
|
+
const chalk = chalkModule.default || chalkModule;
|
|
6
8
|
const EventEmitter = require('events');
|
|
7
9
|
const WebSocket = require('ws');
|
|
8
10
|
|
|
@@ -47,6 +49,13 @@ class MCPClient extends EventEmitter {
|
|
|
47
49
|
/**
|
|
48
50
|
* Initialize MCP client
|
|
49
51
|
*/
|
|
52
|
+
async initialize() {
|
|
53
|
+
return this.initializeMCP();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Initialize MCP client implementation
|
|
58
|
+
*/
|
|
50
59
|
async initializeMCP() {
|
|
51
60
|
console.log(chalk.cyan('🔌 Initializing MCP Client...'));
|
|
52
61
|
|
|
@@ -213,24 +222,38 @@ class MCPClient extends EventEmitter {
|
|
|
213
222
|
});
|
|
214
223
|
|
|
215
224
|
ws.on('error', (error) => {
|
|
216
|
-
|
|
225
|
+
// Gracefully handle connection errors - these are expected for external services
|
|
217
226
|
this.connectionStates.set(serverName, 'error');
|
|
218
|
-
|
|
227
|
+
|
|
228
|
+
// Only log in debug mode
|
|
229
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
230
|
+
console.log(chalk.gray(`🔌 MCP service ${serverName} unavailable: ${error.message}`));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Resolve with null instead of rejecting to allow graceful degradation
|
|
234
|
+
resolve(null);
|
|
219
235
|
});
|
|
220
236
|
|
|
221
237
|
ws.on('close', () => {
|
|
222
|
-
|
|
238
|
+
// Gracefully handle connection close
|
|
223
239
|
this.connectionStates.set(serverName, 'disconnected');
|
|
224
240
|
this.connections.delete(serverName);
|
|
225
241
|
|
|
226
|
-
//
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
}
|
|
242
|
+
// Only log in debug mode
|
|
243
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
244
|
+
console.log(chalk.gray(`🔌 MCP connection to ${serverName} closed`));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Don't attempt automatic reconnection to avoid spam
|
|
230
248
|
});
|
|
231
249
|
|
|
232
250
|
} catch (error) {
|
|
233
|
-
|
|
251
|
+
// Gracefully handle any connection setup errors
|
|
252
|
+
this.connectionStates.set(serverName, 'error');
|
|
253
|
+
if (process.env.RECODER_DEBUG === 'true') {
|
|
254
|
+
console.log(chalk.gray(`🔌 MCP setup failed for ${serverName}: ${error.message}`));
|
|
255
|
+
}
|
|
256
|
+
resolve(null);
|
|
234
257
|
}
|
|
235
258
|
});
|
|
236
259
|
}
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
|
|
8
8
|
const fs = require('fs').promises;
|
|
9
9
|
const path = require('path');
|
|
10
|
-
|
|
10
|
+
// Handle chalk properly
|
|
11
|
+
const chalkModule = require('chalk');
|
|
12
|
+
const chalk = chalkModule.default || chalkModule;;
|
|
11
13
|
const crypto = require('crypto');
|
|
12
14
|
const EventEmitter = require('events');
|
|
13
15
|
|
package/cli/project-manager.js
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const crypto = require('crypto');
|
|
6
|
-
|
|
6
|
+
// Handle chalk properly
|
|
7
|
+
const chalkModule = require('chalk');
|
|
8
|
+
const chalk = chalkModule.default || chalkModule;
|
|
7
9
|
|
|
8
10
|
class ProjectManager {
|
|
9
11
|
constructor() {
|
package/cli/rules-engine.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
|
|
5
|
+
// Handle chalk properly
|
|
6
|
+
const chalkModule = require('chalk');
|
|
7
|
+
const chalk = chalkModule.default || chalkModule;
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* User & Repository Rules Engine
|
|
@@ -411,9 +413,12 @@ class RulesEngine {
|
|
|
411
413
|
getProjectLanguages() {
|
|
412
414
|
// Try to get from project context
|
|
413
415
|
if (this.projectManager) {
|
|
414
|
-
|
|
415
|
-
if (
|
|
416
|
-
|
|
416
|
+
// Fallback for missing getProjectContext method
|
|
417
|
+
if (this.projectManager && typeof this.projectManager.getProjectContext === 'function') {
|
|
418
|
+
const context = this.projectManager.getProjectContext();
|
|
419
|
+
if (context && context.language) {
|
|
420
|
+
return [context.language];
|
|
421
|
+
}
|
|
417
422
|
}
|
|
418
423
|
}
|
|
419
424
|
|
package/cli/run.js
CHANGED
|
@@ -28,6 +28,11 @@ const ScriptsManager = require('./scripts-manager.js');
|
|
|
28
28
|
const GitHubManager = require('./github-manager.js');
|
|
29
29
|
const WorkspaceManager = require('./workspace-manager.js');
|
|
30
30
|
|
|
31
|
+
// Initialize unified error handling
|
|
32
|
+
const UnifiedErrorHandler = require('./unified-error-handler.js');
|
|
33
|
+
const errorHandler = UnifiedErrorHandler.instance;
|
|
34
|
+
errorHandler.initialize();
|
|
35
|
+
|
|
31
36
|
const execAsync = promisify(exec);
|
|
32
37
|
|
|
33
38
|
// Create logs directory if it doesn't exist
|
|
@@ -92,22 +97,72 @@ class RecoderCode {
|
|
|
92
97
|
'X-Title': config.siteName,
|
|
93
98
|
},
|
|
94
99
|
});
|
|
100
|
+
|
|
101
|
+
// Register API error handler with unified error system
|
|
102
|
+
errorHandler.registerHandler('openrouter', (error) => {
|
|
103
|
+
this.handleOpenRouterError(error);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Initialize resource cleanup
|
|
107
|
+
this.systemsInitialized = false;
|
|
108
|
+
this.setupResourceCleanup();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Setup resource cleanup handlers
|
|
113
|
+
*/
|
|
114
|
+
setupResourceCleanup() {
|
|
115
|
+
const cleanup = () => {
|
|
116
|
+
try {
|
|
117
|
+
// Stop any running services
|
|
118
|
+
if (this.mcpClient && typeof this.mcpClient.cleanup === 'function') {
|
|
119
|
+
this.mcpClient.cleanup();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Clean up file watchers via manager
|
|
123
|
+
const FileWatcherManager = require('./file-watcher-manager.js');
|
|
124
|
+
FileWatcherManager.instance.cleanup();
|
|
125
|
+
|
|
126
|
+
// Clean up context engine
|
|
127
|
+
if (this.contextEngine && typeof this.contextEngine.cleanup === 'function') {
|
|
128
|
+
this.contextEngine.cleanup();
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
// Ignore cleanup errors
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
process.once('exit', cleanup);
|
|
136
|
+
process.once('SIGINT', cleanup);
|
|
137
|
+
process.once('SIGTERM', cleanup);
|
|
95
138
|
}
|
|
96
139
|
|
|
97
140
|
/**
|
|
98
141
|
* Initialize advanced systems with full integration
|
|
99
142
|
*/
|
|
100
143
|
async initializeSystems() {
|
|
144
|
+
// Prevent duplicate initialization
|
|
145
|
+
if (this.systemsInitialized) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
101
149
|
try {
|
|
102
|
-
|
|
150
|
+
// Only show technical messages in debug or non-user mode
|
|
151
|
+
if (process.env.RECODER_DEBUG === 'true' || process.env.RECODER_USER_MODE !== 'true') {
|
|
152
|
+
console.log(chalk.gray('🚀 Initializing enhanced AI CLI systems...'));
|
|
153
|
+
}
|
|
103
154
|
|
|
104
155
|
// Initialize context engine for codebase understanding
|
|
105
|
-
this.contextEngine
|
|
106
|
-
|
|
156
|
+
if (!this.contextEngine) {
|
|
157
|
+
this.contextEngine = new ContextEngine();
|
|
158
|
+
await this.contextEngine.initialize();
|
|
159
|
+
}
|
|
107
160
|
|
|
108
161
|
// Initialize MCP client for model communication
|
|
109
|
-
this.mcpClient
|
|
110
|
-
|
|
162
|
+
if (!this.mcpClient) {
|
|
163
|
+
this.mcpClient = new MCPClient();
|
|
164
|
+
await this.mcpClient.initialize();
|
|
165
|
+
}
|
|
111
166
|
|
|
112
167
|
// Initialize model manager with intelligent selection
|
|
113
168
|
this.modelManager = new ModelManager(this.mcpClient, this.contextEngine);
|
|
@@ -168,6 +223,9 @@ class RecoderCode {
|
|
|
168
223
|
});
|
|
169
224
|
}
|
|
170
225
|
|
|
226
|
+
// Mark systems as initialized
|
|
227
|
+
this.systemsInitialized = true;
|
|
228
|
+
|
|
171
229
|
} catch (error) {
|
|
172
230
|
console.log(chalk.yellow(`⚠️ System integration setup failed: ${error.message}`));
|
|
173
231
|
}
|
|
@@ -316,8 +374,10 @@ class RecoderCode {
|
|
|
316
374
|
}
|
|
317
375
|
} catch (error) {
|
|
318
376
|
this.logRequest(payload, null, error);
|
|
319
|
-
|
|
320
|
-
|
|
377
|
+
|
|
378
|
+
// Let unified error handler manage the error instead of re-throwing
|
|
379
|
+
// Return null for graceful degradation
|
|
380
|
+
return null;
|
|
321
381
|
}
|
|
322
382
|
}
|
|
323
383
|
|
|
@@ -748,8 +808,8 @@ Project context: ${this.getProjectContextString()}${this.getRulesContextString()
|
|
|
748
808
|
|
|
749
809
|
// Add safety checks for response structure
|
|
750
810
|
if (!response || !response.choices || !response.choices[0]) {
|
|
751
|
-
|
|
752
|
-
return '
|
|
811
|
+
// API error already handled by unified error handler, provide graceful fallback
|
|
812
|
+
return 'Unable to process request - API service unavailable. Please check your API key and credits.';
|
|
753
813
|
}
|
|
754
814
|
|
|
755
815
|
while (response.choices[0].message && response.choices[0].message.tool_calls) {
|
|
@@ -771,8 +831,8 @@ Project context: ${this.getProjectContextString()}${this.getRulesContextString()
|
|
|
771
831
|
|
|
772
832
|
// Add safety check again
|
|
773
833
|
if (!response || !response.choices || !response.choices[0]) {
|
|
774
|
-
|
|
775
|
-
return '
|
|
834
|
+
// API error already handled by unified error handler, provide graceful fallback
|
|
835
|
+
return 'Unable to complete tool execution - API service unavailable. Please check your API key and credits.';
|
|
776
836
|
}
|
|
777
837
|
}
|
|
778
838
|
|
|
@@ -1193,7 +1253,19 @@ async function main() {
|
|
|
1193
1253
|
}
|
|
1194
1254
|
|
|
1195
1255
|
if (args.length === 0) {
|
|
1196
|
-
// Launch interactive mode
|
|
1256
|
+
// Launch interactive mode with proper user onboarding
|
|
1257
|
+
const UserOnboarding = require('./user-onboarding.js');
|
|
1258
|
+
const onboarding = new UserOnboarding();
|
|
1259
|
+
|
|
1260
|
+
if (onboarding.needsOnboarding()) {
|
|
1261
|
+
// First time user - run full onboarding
|
|
1262
|
+
await onboarding.runOnboarding();
|
|
1263
|
+
} else {
|
|
1264
|
+
// Returning user - quick start
|
|
1265
|
+
await onboarding.quickStart();
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// Now launch interactive mode
|
|
1197
1269
|
const InteractiveChat = require('./interactive.js');
|
|
1198
1270
|
const chat = new InteractiveChat();
|
|
1199
1271
|
chat.start();
|
|
@@ -2267,7 +2339,12 @@ async function main() {
|
|
|
2267
2339
|
}
|
|
2268
2340
|
|
|
2269
2341
|
if (!prompt) {
|
|
2270
|
-
console.error('Error: No prompt provided');
|
|
2342
|
+
console.error(chalk.red('❌ Error: No prompt provided'));
|
|
2343
|
+
console.log(chalk.yellow('💡 Usage examples:'));
|
|
2344
|
+
console.log(chalk.white(' recoder-code "Hello, how can you help me?"'));
|
|
2345
|
+
console.log(chalk.white(' recoder-code --help'));
|
|
2346
|
+
console.log(chalk.white(' recoder-code --setup'));
|
|
2347
|
+
console.log(chalk.gray('\nFor interactive mode, run: recoder-code'));
|
|
2271
2348
|
process.exit(1);
|
|
2272
2349
|
}
|
|
2273
2350
|
|
package/cli/setup-wizard.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const readline = require('readline');
|
|
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
|
|
package/cli/slash-commands.js
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
|
|
5
|
+
// Handle chalk properly
|
|
6
|
+
const chalkModule = require('chalk');
|
|
7
|
+
const chalk = chalkModule.default || chalkModule;
|
|
6
8
|
const inquirer = require('inquirer');
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -10,10 +12,11 @@ const inquirer = require('inquirer');
|
|
|
10
12
|
* Flexible AI agent framework for specialized tasks
|
|
11
13
|
*/
|
|
12
14
|
class SlashCommandsEngine {
|
|
13
|
-
constructor(contextEngine, projectManager, visionAnalyzer = null) {
|
|
15
|
+
constructor(contextEngine, projectManager, visionAnalyzer = null, todoManager = null) {
|
|
14
16
|
this.contextEngine = contextEngine;
|
|
15
17
|
this.projectManager = projectManager;
|
|
16
18
|
this.visionAnalyzer = visionAnalyzer;
|
|
19
|
+
this.todoManager = todoManager;
|
|
17
20
|
this.commands = new Map();
|
|
18
21
|
this.aliases = new Map();
|
|
19
22
|
this.commandHistory = [];
|
|
@@ -186,6 +189,21 @@ class SlashCommandsEngine {
|
|
|
186
189
|
});
|
|
187
190
|
}
|
|
188
191
|
|
|
192
|
+
// Todo Management Commands for Production Use
|
|
193
|
+
this.registerCommand({
|
|
194
|
+
name: 'todo',
|
|
195
|
+
aliases: ['task', 'todos'],
|
|
196
|
+
description: 'Production-ready todo and task management system',
|
|
197
|
+
category: 'productivity',
|
|
198
|
+
agent: this.createTodoAgent(),
|
|
199
|
+
options: {
|
|
200
|
+
action: { type: 'string', default: 'list', choices: ['list', 'add', 'complete', 'start', 'delete', 'stats', 'search'] },
|
|
201
|
+
priority: { type: 'string', default: 'medium', choices: ['low', 'medium', 'high'] },
|
|
202
|
+
category: { type: 'string', default: 'general' },
|
|
203
|
+
show_completed: { type: 'boolean', default: true }
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
189
207
|
console.log(chalk.green(`✅ Loaded ${this.commands.size} built-in commands`));
|
|
190
208
|
}
|
|
191
209
|
|
|
@@ -234,7 +252,7 @@ class SlashCommandsEngine {
|
|
|
234
252
|
const mergedOptions = this.mergeOptions(commandDef.options, args, options);
|
|
235
253
|
|
|
236
254
|
// Generate context for the command
|
|
237
|
-
const context = await this.generateCommandContext(commandDef, mergedOptions);
|
|
255
|
+
const context = await this.generateCommandContext(commandDef, mergedOptions, args);
|
|
238
256
|
|
|
239
257
|
// Execute the agent
|
|
240
258
|
const result = await commandDef.agent.execute(context, mergedOptions);
|
|
@@ -310,14 +328,16 @@ class SlashCommandsEngine {
|
|
|
310
328
|
/**
|
|
311
329
|
* Generate context for command execution
|
|
312
330
|
*/
|
|
313
|
-
async generateCommandContext(commandDef, options) {
|
|
331
|
+
async generateCommandContext(commandDef, options, args = []) {
|
|
314
332
|
const context = {
|
|
315
333
|
command: commandDef.name,
|
|
316
334
|
category: commandDef.category,
|
|
317
335
|
options: options,
|
|
336
|
+
args: args,
|
|
318
337
|
codebase: null,
|
|
319
338
|
relevantFiles: [],
|
|
320
|
-
projectInfo: null
|
|
339
|
+
projectInfo: null,
|
|
340
|
+
todoManager: this.todoManager
|
|
321
341
|
};
|
|
322
342
|
|
|
323
343
|
// Get codebase context if context engine is available
|
|
@@ -1185,6 +1205,106 @@ class SlashCommandsEngine {
|
|
|
1185
1205
|
}
|
|
1186
1206
|
}
|
|
1187
1207
|
|
|
1208
|
+
/**
|
|
1209
|
+
* Create Todo Management Agent
|
|
1210
|
+
*/
|
|
1211
|
+
createTodoAgent() {
|
|
1212
|
+
return {
|
|
1213
|
+
name: 'TodoAgent',
|
|
1214
|
+
async execute(context, options) {
|
|
1215
|
+
// Get todo manager from interactive instance
|
|
1216
|
+
const todoManager = context.todoManager || new (require('./todo-manager.js'))();
|
|
1217
|
+
|
|
1218
|
+
switch (options.action) {
|
|
1219
|
+
case 'list':
|
|
1220
|
+
console.log('');
|
|
1221
|
+
todoManager.displayTodos(options.show_completed);
|
|
1222
|
+
break;
|
|
1223
|
+
|
|
1224
|
+
case 'add':
|
|
1225
|
+
if (!context.args || context.args.length === 0) {
|
|
1226
|
+
console.log(chalk.yellow('⚠️ Usage: /todo add <task description>'));
|
|
1227
|
+
return;
|
|
1228
|
+
}
|
|
1229
|
+
const content = context.args.join(' ');
|
|
1230
|
+
const id = todoManager.addTodo(content, options.priority, options.category);
|
|
1231
|
+
console.log(chalk.green(`✅ Added todo: ${content}`));
|
|
1232
|
+
console.log(chalk.gray(` ID: ${id}, Priority: ${options.priority}, Category: ${options.category}`));
|
|
1233
|
+
break;
|
|
1234
|
+
|
|
1235
|
+
case 'complete':
|
|
1236
|
+
if (!context.args || context.args.length === 0) {
|
|
1237
|
+
console.log(chalk.yellow('⚠️ Usage: /todo complete <id>'));
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
if (todoManager.completeTodo(context.args[0])) {
|
|
1241
|
+
console.log(chalk.green('✅ Todo marked as completed'));
|
|
1242
|
+
} else {
|
|
1243
|
+
console.log(chalk.red('❌ Todo not found'));
|
|
1244
|
+
}
|
|
1245
|
+
break;
|
|
1246
|
+
|
|
1247
|
+
case 'start':
|
|
1248
|
+
if (!context.args || context.args.length === 0) {
|
|
1249
|
+
console.log(chalk.yellow('⚠️ Usage: /todo start <id>'));
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
if (todoManager.startTodo(context.args[0])) {
|
|
1253
|
+
console.log(chalk.yellow('◐ Todo marked as in progress'));
|
|
1254
|
+
} else {
|
|
1255
|
+
console.log(chalk.red('❌ Todo not found'));
|
|
1256
|
+
}
|
|
1257
|
+
break;
|
|
1258
|
+
|
|
1259
|
+
case 'delete':
|
|
1260
|
+
if (!context.args || context.args.length === 0) {
|
|
1261
|
+
console.log(chalk.yellow('⚠️ Usage: /todo delete <id>'));
|
|
1262
|
+
return;
|
|
1263
|
+
}
|
|
1264
|
+
if (todoManager.deleteTodo(context.args[0])) {
|
|
1265
|
+
console.log(chalk.green('✅ Todo deleted'));
|
|
1266
|
+
} else {
|
|
1267
|
+
console.log(chalk.red('❌ Todo not found'));
|
|
1268
|
+
}
|
|
1269
|
+
break;
|
|
1270
|
+
|
|
1271
|
+
case 'stats':
|
|
1272
|
+
console.log('');
|
|
1273
|
+
todoManager.displayStats();
|
|
1274
|
+
break;
|
|
1275
|
+
|
|
1276
|
+
case 'search':
|
|
1277
|
+
if (!context.args || context.args.length === 0) {
|
|
1278
|
+
console.log(chalk.yellow('⚠️ Usage: /todo search <query>'));
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
const query = context.args.join(' ');
|
|
1282
|
+
todoManager.searchTodos(query);
|
|
1283
|
+
break;
|
|
1284
|
+
|
|
1285
|
+
default:
|
|
1286
|
+
console.log(chalk.cyan.bold('Todo Management System'));
|
|
1287
|
+
console.log('');
|
|
1288
|
+
console.log(chalk.white('Available actions:'));
|
|
1289
|
+
console.log(chalk.gray(' /todo list - Show all todos'));
|
|
1290
|
+
console.log(chalk.gray(' /todo add <task> - Add new todo'));
|
|
1291
|
+
console.log(chalk.gray(' /todo complete <id> - Mark todo as complete'));
|
|
1292
|
+
console.log(chalk.gray(' /todo start <id> - Mark todo as in progress'));
|
|
1293
|
+
console.log(chalk.gray(' /todo delete <id> - Delete todo'));
|
|
1294
|
+
console.log(chalk.gray(' /todo stats - Show statistics'));
|
|
1295
|
+
console.log(chalk.gray(' /todo search <query> - Search todos'));
|
|
1296
|
+
break;
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
return {
|
|
1300
|
+
success: true,
|
|
1301
|
+
action: options.action,
|
|
1302
|
+
timestamp: new Date().toISOString()
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1188
1308
|
/**
|
|
1189
1309
|
* Get command suggestions based on context
|
|
1190
1310
|
*/
|
|
@@ -1203,6 +1323,13 @@ class SlashCommandsEngine {
|
|
|
1203
1323
|
suggestions.push('/review --focus performance');
|
|
1204
1324
|
}
|
|
1205
1325
|
|
|
1326
|
+
// Todo-focused suggestions
|
|
1327
|
+
if (context.query && (context.query.toLowerCase().includes('todo') || context.query.toLowerCase().includes('task'))) {
|
|
1328
|
+
suggestions.push('/todo list');
|
|
1329
|
+
suggestions.push('/todo add <task description>');
|
|
1330
|
+
suggestions.push('/todo stats');
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1206
1333
|
return suggestions;
|
|
1207
1334
|
}
|
|
1208
1335
|
}
|