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/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
- const chalk = require('chalk');
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
- console.log(chalk.red(`❌ Connection error for ${serverName}: ${error.message}`));
225
+ // Gracefully handle connection errors - these are expected for external services
217
226
  this.connectionStates.set(serverName, 'error');
218
- reject(error);
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
- console.log(chalk.yellow(`⚠️ Connection closed for ${serverName}`));
238
+ // Gracefully handle connection close
223
239
  this.connectionStates.set(serverName, 'disconnected');
224
240
  this.connections.delete(serverName);
225
241
 
226
- // Attempt reconnection
227
- setTimeout(() => {
228
- this.reconnectToServer(serverName);
229
- }, 5000);
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
- reject(error);
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
- const chalk = require('chalk');
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
 
@@ -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
  * Natural Language Processor
@@ -3,7 +3,9 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const crypto = require('crypto');
6
- const chalk = require('chalk');
6
+ // Handle chalk properly
7
+ const chalkModule = require('chalk');
8
+ const chalk = chalkModule.default || chalkModule;
7
9
 
8
10
  class ProjectManager {
9
11
  constructor() {
@@ -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
  * 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
- const context = this.projectManager.getProjectContext();
415
- if (context && context.language) {
416
- return [context.language];
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
- console.log(chalk.gray('🚀 Initializing enhanced AI CLI systems...'));
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 = new ContextEngine();
106
- await this.contextEngine.initialize();
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 = new MCPClient();
110
- await this.mcpClient.initialize();
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
- this.handleOpenRouterError(error);
320
- throw error;
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
- console.error('Invalid response structure from OpenRouter');
752
- return 'Error: Invalid response received from API';
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
- console.error('Invalid response structure from OpenRouter in tool loop');
775
- return 'Error: Invalid response received from API during tool execution';
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 when no arguments provided (skip API key check for 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
 
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const readline = require('readline');
4
- const chalk = require('chalk');
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
 
@@ -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
  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
  }