recoder-code 2.2.0 → 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.
@@ -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
  }
@@ -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
 
8
10
  /**
@@ -482,7 +484,7 @@ class TaskManager extends EventEmitter {
482
484
  console.log(chalk.gray('🤖 Starting automation engine...'));
483
485
 
484
486
  // Set up file watchers for automated triggers
485
- if (this.contextEngine && this.contextEngine.fileWatcher) {
487
+ if (this.contextEngine && this.contextEngine.fileWatcher && typeof this.contextEngine.on === 'function') {
486
488
  this.contextEngine.on('fileChanged', (filePath, eventType) => {
487
489
  this.handleFileChangeAutomation(filePath, eventType);
488
490
  });
@@ -1080,13 +1082,19 @@ class TaskManager extends EventEmitter {
1080
1082
  this.setupGitHooksAutomation();
1081
1083
 
1082
1084
  // Dependency change automation
1083
- this.setupDependencyAutomation();
1085
+ if (typeof this.setupDependencyAutomation === 'function') {
1086
+ this.setupDependencyAutomation();
1087
+ }
1084
1088
 
1085
1089
  // Performance monitoring automation
1086
- this.setupPerformanceAutomation();
1090
+ if (typeof this.setupPerformanceAutomation === 'function') {
1091
+ this.setupPerformanceAutomation();
1092
+ }
1087
1093
 
1088
1094
  // Security monitoring automation
1089
- this.setupSecurityAutomation();
1095
+ if (typeof this.setupSecurityAutomation === 'function') {
1096
+ this.setupSecurityAutomation();
1097
+ }
1090
1098
  }
1091
1099
 
1092
1100
  /**
@@ -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 WebSocket = require('ws');
13
15
  const EventEmitter = require('events');
@@ -0,0 +1,391 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ // Handle chalk properly
6
+ const chalkModule = require('chalk');
7
+ const chalk = chalkModule.default || chalkModule;
8
+
9
+ /**
10
+ * Production-Ready Todo Management System for Recoder Code
11
+ * Provides visual todo management with checkboxes and status tracking
12
+ */
13
+ class TodoManager {
14
+ constructor(options = {}) {
15
+ this.todoFile = options.todoFile || path.join(process.cwd(), '.recoder-todos.json');
16
+ this.todos = [];
17
+ this.currentUser = options.user || this.getCurrentUser();
18
+ this.loadTodos();
19
+ }
20
+
21
+ getCurrentUser() {
22
+ return process.env.USER || process.env.USERNAME || 'developer';
23
+ }
24
+
25
+ /**
26
+ * Load todos from file
27
+ */
28
+ loadTodos() {
29
+ try {
30
+ if (fs.existsSync(this.todoFile)) {
31
+ const data = JSON.parse(fs.readFileSync(this.todoFile, 'utf8'));
32
+ this.todos = data.todos || [];
33
+ }
34
+ } catch (error) {
35
+ console.log(chalk.yellow(`⚠️ Could not load todos: ${error.message}`));
36
+ this.todos = [];
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Save todos to file
42
+ */
43
+ saveTodos() {
44
+ try {
45
+ const data = {
46
+ todos: this.todos,
47
+ lastUpdated: new Date().toISOString(),
48
+ user: this.currentUser
49
+ };
50
+ fs.writeFileSync(this.todoFile, JSON.stringify(data, null, 2));
51
+ } catch (error) {
52
+ console.log(chalk.red(`❌ Could not save todos: ${error.message}`));
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Add a new todo
58
+ */
59
+ addTodo(content, priority = 'medium', category = 'general') {
60
+ const todo = {
61
+ id: this.generateId(),
62
+ content: content,
63
+ status: 'pending',
64
+ priority: priority,
65
+ category: category,
66
+ createdAt: new Date().toISOString(),
67
+ createdBy: this.currentUser,
68
+ updatedAt: new Date().toISOString()
69
+ };
70
+
71
+ this.todos.push(todo);
72
+ this.saveTodos();
73
+ return todo.id;
74
+ }
75
+
76
+ /**
77
+ * Update todo status
78
+ */
79
+ updateTodoStatus(id, status) {
80
+ const todo = this.todos.find(t => t.id === id);
81
+ if (todo) {
82
+ todo.status = status;
83
+ todo.updatedAt = new Date().toISOString();
84
+ this.saveTodos();
85
+ return true;
86
+ }
87
+ return false;
88
+ }
89
+
90
+ /**
91
+ * Mark todo as completed
92
+ */
93
+ completeTodo(id) {
94
+ return this.updateTodoStatus(id, 'completed');
95
+ }
96
+
97
+ /**
98
+ * Mark todo as in progress
99
+ */
100
+ startTodo(id) {
101
+ return this.updateTodoStatus(id, 'in_progress');
102
+ }
103
+
104
+ /**
105
+ * Delete a todo
106
+ */
107
+ deleteTodo(id) {
108
+ const index = this.todos.findIndex(t => t.id === id);
109
+ if (index !== -1) {
110
+ this.todos.splice(index, 1);
111
+ this.saveTodos();
112
+ return true;
113
+ }
114
+ return false;
115
+ }
116
+
117
+ /**
118
+ * Display todos with visual interface like shown
119
+ */
120
+ displayTodos(showCompleted = true) {
121
+ console.log(chalk.cyan.bold('Update Todos'));
122
+
123
+ if (this.todos.length === 0) {
124
+ console.log(chalk.gray(' ⎿ No todos found. Add one with: /todo add <task>'));
125
+ return;
126
+ }
127
+
128
+ // Group todos by status
129
+ const pending = this.todos.filter(t => t.status === 'pending');
130
+ const inProgress = this.todos.filter(t => t.status === 'in_progress');
131
+ const completed = this.todos.filter(t => t.status === 'completed');
132
+
133
+ // Display in progress first
134
+ if (inProgress.length > 0) {
135
+ console.log(chalk.yellow(' ⎿ ◐ In Progress:'));
136
+ inProgress.forEach(todo => {
137
+ console.log(chalk.yellow(` ◐ ${todo.content}`));
138
+ });
139
+ }
140
+
141
+ // Display pending todos
142
+ if (pending.length > 0) {
143
+ console.log(chalk.white(' ⎿ ☐ Pending:'));
144
+ pending.forEach(todo => {
145
+ const priorityIcon = this.getPriorityIcon(todo.priority);
146
+ console.log(chalk.white(` ☐ ${priorityIcon} ${todo.content}`));
147
+ });
148
+ }
149
+
150
+ // Display completed todos if requested
151
+ if (showCompleted && completed.length > 0) {
152
+ console.log(chalk.green(' ⎿ ☒ Completed:'));
153
+ completed.forEach(todo => {
154
+ console.log(chalk.green(` ☒ ${todo.content}`));
155
+ });
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Get priority icon
161
+ */
162
+ getPriorityIcon(priority) {
163
+ switch (priority) {
164
+ case 'high': return '🔴';
165
+ case 'medium': return '🟡';
166
+ case 'low': return '🟢';
167
+ default: return '⚪';
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Display todos by category
173
+ */
174
+ displayTodosByCategory() {
175
+ const categories = {};
176
+ this.todos.forEach(todo => {
177
+ if (!categories[todo.category]) {
178
+ categories[todo.category] = [];
179
+ }
180
+ categories[todo.category].push(todo);
181
+ });
182
+
183
+ Object.keys(categories).forEach(category => {
184
+ console.log(chalk.cyan.bold(`\n📋 ${category.toUpperCase()}`));
185
+ categories[category].forEach(todo => {
186
+ const statusIcon = this.getStatusIcon(todo.status);
187
+ const priorityIcon = this.getPriorityIcon(todo.priority);
188
+ console.log(` ${statusIcon} ${priorityIcon} ${todo.content}`);
189
+ });
190
+ });
191
+ }
192
+
193
+ /**
194
+ * Get status icon
195
+ */
196
+ getStatusIcon(status) {
197
+ switch (status) {
198
+ case 'completed': return chalk.green('☒');
199
+ case 'in_progress': return chalk.yellow('◐');
200
+ case 'pending': return chalk.white('☐');
201
+ default: return '⚪';
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Generate unique ID
207
+ */
208
+ generateId() {
209
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
210
+ }
211
+
212
+ /**
213
+ * Get statistics
214
+ */
215
+ getStats() {
216
+ const total = this.todos.length;
217
+ const completed = this.todos.filter(t => t.status === 'completed').length;
218
+ const inProgress = this.todos.filter(t => t.status === 'in_progress').length;
219
+ const pending = this.todos.filter(t => t.status === 'pending').length;
220
+
221
+ return {
222
+ total,
223
+ completed,
224
+ inProgress,
225
+ pending,
226
+ completionRate: total > 0 ? Math.round((completed / total) * 100) : 0
227
+ };
228
+ }
229
+
230
+ /**
231
+ * Display statistics
232
+ */
233
+ displayStats() {
234
+ const stats = this.getStats();
235
+ console.log(chalk.cyan.bold('📊 Todo Statistics'));
236
+ console.log(chalk.white(`Total: ${stats.total}`));
237
+ console.log(chalk.green(`Completed: ${stats.completed}`));
238
+ console.log(chalk.yellow(`In Progress: ${stats.inProgress}`));
239
+ console.log(chalk.gray(`Pending: ${stats.pending}`));
240
+ console.log(chalk.blue(`Completion Rate: ${stats.completionRate}%`));
241
+ }
242
+
243
+ /**
244
+ * Clear completed todos
245
+ */
246
+ clearCompleted() {
247
+ const beforeCount = this.todos.length;
248
+ this.todos = this.todos.filter(t => t.status !== 'completed');
249
+ const removedCount = beforeCount - this.todos.length;
250
+
251
+ if (removedCount > 0) {
252
+ this.saveTodos();
253
+ console.log(chalk.green(`✅ Cleared ${removedCount} completed todos`));
254
+ } else {
255
+ console.log(chalk.gray('No completed todos to clear'));
256
+ }
257
+ }
258
+
259
+ /**
260
+ * Search todos
261
+ */
262
+ searchTodos(query) {
263
+ const results = this.todos.filter(todo =>
264
+ todo.content.toLowerCase().includes(query.toLowerCase()) ||
265
+ todo.category.toLowerCase().includes(query.toLowerCase())
266
+ );
267
+
268
+ if (results.length === 0) {
269
+ console.log(chalk.gray(`No todos found matching: ${query}`));
270
+ return;
271
+ }
272
+
273
+ console.log(chalk.cyan.bold(`🔍 Search Results for "${query}":`));
274
+ results.forEach(todo => {
275
+ const statusIcon = this.getStatusIcon(todo.status);
276
+ const priorityIcon = this.getPriorityIcon(todo.priority);
277
+ console.log(` ${statusIcon} ${priorityIcon} ${todo.content}`);
278
+ });
279
+ }
280
+
281
+ /**
282
+ * Import todos from existing TodoWrite format
283
+ */
284
+ importFromTodoWrite(todoWriteTodos) {
285
+ todoWriteTodos.forEach(todo => {
286
+ this.addTodo(todo.content, 'medium', 'imported');
287
+ if (todo.status !== 'pending') {
288
+ this.updateTodoStatus(this.todos[this.todos.length - 1].id, todo.status);
289
+ }
290
+ });
291
+ console.log(chalk.green(`✅ Imported ${todoWriteTodos.length} todos`));
292
+ }
293
+ }
294
+
295
+ module.exports = TodoManager;
296
+
297
+ // CLI interface when run directly
298
+ if (require.main === module) {
299
+ const todoManager = new TodoManager();
300
+ const command = process.argv[2];
301
+ const args = process.argv.slice(3);
302
+
303
+ switch (command) {
304
+ case 'add':
305
+ if (args.length === 0) {
306
+ console.log('Usage: todo-manager.js add <content> [priority] [category]');
307
+ process.exit(1);
308
+ }
309
+ const content = args[0];
310
+ const priority = args[1] || 'medium';
311
+ const category = args[2] || 'general';
312
+ const id = todoManager.addTodo(content, priority, category);
313
+ console.log(chalk.green(`✅ Added todo: ${id}`));
314
+ break;
315
+
316
+ case 'list':
317
+ todoManager.displayTodos();
318
+ break;
319
+
320
+ case 'complete':
321
+ if (args.length === 0) {
322
+ console.log('Usage: todo-manager.js complete <id>');
323
+ process.exit(1);
324
+ }
325
+ if (todoManager.completeTodo(args[0])) {
326
+ console.log(chalk.green('✅ Todo marked as completed'));
327
+ } else {
328
+ console.log(chalk.red('❌ Todo not found'));
329
+ }
330
+ break;
331
+
332
+ case 'start':
333
+ if (args.length === 0) {
334
+ console.log('Usage: todo-manager.js start <id>');
335
+ process.exit(1);
336
+ }
337
+ if (todoManager.startTodo(args[0])) {
338
+ console.log(chalk.yellow('◐ Todo marked as in progress'));
339
+ } else {
340
+ console.log(chalk.red('❌ Todo not found'));
341
+ }
342
+ break;
343
+
344
+ case 'delete':
345
+ if (args.length === 0) {
346
+ console.log('Usage: todo-manager.js delete <id>');
347
+ process.exit(1);
348
+ }
349
+ if (todoManager.deleteTodo(args[0])) {
350
+ console.log(chalk.green('✅ Todo deleted'));
351
+ } else {
352
+ console.log(chalk.red('❌ Todo not found'));
353
+ }
354
+ break;
355
+
356
+ case 'stats':
357
+ todoManager.displayStats();
358
+ break;
359
+
360
+ case 'clear':
361
+ todoManager.clearCompleted();
362
+ break;
363
+
364
+ case 'search':
365
+ if (args.length === 0) {
366
+ console.log('Usage: todo-manager.js search <query>');
367
+ process.exit(1);
368
+ }
369
+ todoManager.searchTodos(args[0]);
370
+ break;
371
+
372
+ case 'categories':
373
+ todoManager.displayTodosByCategory();
374
+ break;
375
+
376
+ default:
377
+ console.log(chalk.cyan.bold('Recoder Code - Todo Manager'));
378
+ console.log('');
379
+ console.log('Usage:');
380
+ console.log(' todo-manager.js add <content> [priority] [category]');
381
+ console.log(' todo-manager.js list');
382
+ console.log(' todo-manager.js complete <id>');
383
+ console.log(' todo-manager.js start <id>');
384
+ console.log(' todo-manager.js delete <id>');
385
+ console.log(' todo-manager.js stats');
386
+ console.log(' todo-manager.js clear');
387
+ console.log(' todo-manager.js search <query>');
388
+ console.log(' todo-manager.js categories');
389
+ break;
390
+ }
391
+ }