@@ -31,10 +31,11 @@ export class TaskManagerServer {
31
31
private taskCounter = 0 ;
32
32
private data : TaskManagerFile = { projects : [ ] } ;
33
33
private filePath : string ;
34
+ private initialized : Promise < void > ;
34
35
35
36
constructor ( testFilePath ?: string ) {
36
37
this . filePath = testFilePath || TASK_FILE_PATH ;
37
- this . loadTasks ( ) ;
38
+ this . initialized = this . loadTasks ( ) ;
38
39
}
39
40
40
41
private async loadTasks ( ) {
@@ -66,6 +67,10 @@ export class TaskManagerServer {
66
67
}
67
68
}
68
69
70
+ private async ensureInitialized ( ) {
71
+ await this . initialized ;
72
+ }
73
+
69
74
private async saveTasks ( ) {
70
75
try {
71
76
// Ensure directory exists before writing
@@ -91,13 +96,15 @@ export class TaskManagerServer {
91
96
if ( ! proj ) return "Project not found" ;
92
97
93
98
let table = "\nProgress Status:\n" ;
94
- table += "| Task ID | Title | Description | Status | Approval |\n" ;
95
- table += "|----------|----------|------|------|----------|\n" ;
99
+ table += "| Task ID | Title | Description | Status | Approval | Tools | Rules | \n" ;
100
+ table += "|----------|----------|------|------|----------|--------|--------| \n" ;
96
101
97
102
for ( const task of proj . tasks ) {
98
103
const status = task . status === "done" ? "✅ Done" : ( task . status === "in progress" ? "🔄 In Progress" : "⏳ Not Started" ) ;
99
104
const approved = task . approved ? "✅ Approved" : "⏳ Pending" ;
100
- table += `| ${ task . id } | ${ task . title } | ${ task . description } | ${ status } | ${ approved } |\n` ;
105
+ const tools = task . toolRecommendations ? "✓" : "-" ;
106
+ const rules = task . ruleRecommendations ? "✓" : "-" ;
107
+ table += `| ${ task . id } | ${ task . title } | ${ task . description } | ${ status } | ${ approved } | ${ tools } | ${ rules } |\n` ;
101
108
}
102
109
103
110
return table ;
@@ -122,10 +129,10 @@ export class TaskManagerServer {
122
129
123
130
public async createProject (
124
131
initialPrompt : string ,
125
- tasks : { title : string ; description : string } [ ] ,
132
+ tasks : { title : string ; description : string ; toolRecommendations ?: string ; ruleRecommendations ?: string } [ ] ,
126
133
projectPlan ?: string
127
134
) {
128
- await this . loadTasks ( ) ;
135
+ await this . ensureInitialized ( ) ;
129
136
this . projectCounter += 1 ;
130
137
const projectId = `proj-${ this . projectCounter } ` ;
131
138
@@ -139,6 +146,8 @@ export class TaskManagerServer {
139
146
status : "not started" ,
140
147
approved : false ,
141
148
completedDetails : "" ,
149
+ toolRecommendations : taskDef . toolRecommendations ,
150
+ ruleRecommendations : taskDef . ruleRecommendations ,
142
151
} ) ;
143
152
}
144
153
@@ -168,7 +177,7 @@ export class TaskManagerServer {
168
177
}
169
178
170
179
public async getNextTask ( projectId : string ) {
171
- await this . loadTasks ( ) ;
180
+ await this . ensureInitialized ( ) ;
172
181
const proj = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
173
182
if ( ! proj ) {
174
183
return { status : "error" , message : "Project not found" } ;
@@ -210,7 +219,7 @@ export class TaskManagerServer {
210
219
taskId : string ,
211
220
completedDetails ?: string
212
221
) {
213
- await this . loadTasks ( ) ;
222
+ await this . ensureInitialized ( ) ;
214
223
const proj = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
215
224
if ( ! proj ) return { status : "error" , message : "Project not found" } ;
216
225
const task = proj . tasks . find ( ( t ) => t . id === taskId ) ;
@@ -238,7 +247,7 @@ export class TaskManagerServer {
238
247
}
239
248
240
249
public async approveTaskCompletion ( projectId : string , taskId : string ) {
241
- await this . loadTasks ( ) ;
250
+ await this . ensureInitialized ( ) ;
242
251
const proj = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
243
252
if ( ! proj ) return { status : "error" , message : "Project not found" } ;
244
253
const task = proj . tasks . find ( ( t ) => t . id === taskId ) ;
@@ -263,7 +272,7 @@ export class TaskManagerServer {
263
272
}
264
273
265
274
public async approveProjectCompletion ( projectId : string ) {
266
- await this . loadTasks ( ) ;
275
+ await this . ensureInitialized ( ) ;
267
276
const proj = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
268
277
if ( ! proj ) return { status : "error" , message : "Project not found" } ;
269
278
@@ -292,7 +301,7 @@ export class TaskManagerServer {
292
301
}
293
302
294
303
public async openTaskDetails ( taskId : string ) {
295
- await this . loadTasks ( ) ;
304
+ await this . ensureInitialized ( ) ;
296
305
for ( const proj of this . data . projects ) {
297
306
const target = proj . tasks . find ( ( t ) => t . id === taskId ) ;
298
307
if ( target ) {
@@ -317,18 +326,19 @@ export class TaskManagerServer {
317
326
}
318
327
319
328
public async listProjects ( state ?: TaskState ) {
320
- await this . loadTasks ( ) ;
321
- let filteredProjects = this . data . projects ;
329
+ await this . ensureInitialized ( ) ;
330
+
331
+ let filteredProjects = [ ...this . data . projects ] ;
322
332
323
333
if ( state && state !== "all" ) {
324
- filteredProjects = this . data . projects . filter ( proj => {
334
+ filteredProjects = filteredProjects . filter ( ( proj ) => {
325
335
switch ( state ) {
326
336
case "open" :
327
- return ! proj . completed && proj . tasks . some ( task => task . status !== "done" ) ;
337
+ return ! proj . completed && proj . tasks . some ( ( task ) => task . status !== "done" ) ;
328
338
case "pending_approval" :
329
- return proj . tasks . some ( task => task . status === "done" && ! task . approved ) ;
339
+ return proj . tasks . some ( ( task ) => task . status === "done" && ! task . approved ) ;
330
340
case "completed" :
331
- return proj . completed && proj . tasks . every ( task => task . status === "done" && task . approved ) ;
341
+ return proj . completed && proj . tasks . every ( ( task ) => task . status === "done" && task . approved ) ;
332
342
default :
333
343
return true ; // Should not happen due to type safety
334
344
}
@@ -343,34 +353,37 @@ export class TaskManagerServer {
343
353
projectId : proj . projectId ,
344
354
initialPrompt : proj . initialPrompt ,
345
355
totalTasks : proj . tasks . length ,
346
- completedTasks : proj . tasks . filter ( ( t ) => t . status === "done" ) . length ,
347
- approvedTasks : proj . tasks . filter ( ( t ) => t . approved ) . length ,
356
+ completedTasks : proj . tasks . filter ( ( task ) => task . status === "done" ) . length ,
357
+ approvedTasks : proj . tasks . filter ( ( task ) => task . approved ) . length ,
348
358
} ) ) ,
349
359
} ;
350
360
}
351
361
352
362
public async listTasks ( projectId ?: string , state ?: TaskState ) {
353
- await this . loadTasks ( ) ;
354
- let tasks : Task [ ] = [ ] ;
355
-
363
+ await this . ensureInitialized ( ) ;
364
+
365
+ // If projectId is provided, verify the project exists
356
366
if ( projectId ) {
357
- const project = this . data . projects . find ( p => p . projectId === projectId ) ;
367
+ const project = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
358
368
if ( ! project ) {
359
- return { status : 'error' , message : 'Project not found' } ;
369
+ return {
370
+ status : "error" ,
371
+ message : "Project not found"
372
+ } ;
360
373
}
361
- tasks = project . tasks ;
362
- } else {
363
- // Flatten all tasks from all projects if no projectId is given
364
- tasks = this . data . projects . flatMap ( project => project . tasks ) ;
365
374
}
366
375
376
+ // Flatten all tasks from all projects if no projectId is given
377
+ let tasks = projectId
378
+ ? this . data . projects . find ( ( p ) => p . projectId === projectId ) ?. tasks || [ ]
379
+ : this . data . projects . flatMap ( ( p ) => p . tasks ) ;
380
+
367
381
// Apply state filtering
368
- let filteredTasks = tasks ;
369
382
if ( state && state !== "all" ) {
370
- filteredTasks = tasks . filter ( task => {
383
+ tasks = tasks . filter ( ( task ) => {
371
384
switch ( state ) {
372
385
case "open" :
373
- return task . status === "not started" || task . status === "in progress ";
386
+ return task . status !== "done ";
374
387
case "pending_approval" :
375
388
return task . status === "done" && ! task . approved ;
376
389
case "completed" :
@@ -383,29 +396,29 @@ export class TaskManagerServer {
383
396
384
397
return {
385
398
status : "tasks_listed" ,
386
- message : `Tasks in the system${ projectId ? ` for project ${ projectId } ` : "" } :\n${ filteredTasks . length } tasks found.` ,
387
- tasks : filteredTasks . map ( task => ( {
399
+ message : `Tasks in the system${ projectId ? ` for project ${ projectId } ` : "" } :\n${ tasks . length } tasks found.` ,
400
+ tasks : tasks . map ( task => ( {
388
401
id : task . id ,
389
402
title : task . title ,
390
403
description : task . description ,
391
404
status : task . status ,
392
- approved : task . approved
405
+ approved : task . approved ,
406
+ completedDetails : task . completedDetails ,
407
+ toolRecommendations : task . toolRecommendations ,
408
+ ruleRecommendations : task . ruleRecommendations
393
409
} ) )
394
410
} ;
395
411
}
396
412
397
413
public async addTasksToProject (
398
414
projectId : string ,
399
- tasks : { title : string ; description : string } [ ]
415
+ tasks : { title : string ; description : string ; toolRecommendations ?: string ; ruleRecommendations ?: string } [ ]
400
416
) {
401
- await this . loadTasks ( ) ;
417
+ await this . ensureInitialized ( ) ;
402
418
const proj = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
403
- if ( ! proj ) return { status : "error" , message : "Project not found" } ;
404
- if ( proj . completed )
405
- return {
406
- status : "error" ,
407
- message : "Cannot add tasks to completed project" ,
408
- } ;
419
+ if ( ! proj ) {
420
+ return { status : "error" , message : "Project not found" } ;
421
+ }
409
422
410
423
const newTasks : Task [ ] = [ ] ;
411
424
for ( const taskDef of tasks ) {
@@ -417,6 +430,8 @@ export class TaskManagerServer {
417
430
status : "not started" ,
418
431
approved : false ,
419
432
completedDetails : "" ,
433
+ toolRecommendations : taskDef . toolRecommendations ,
434
+ ruleRecommendations : taskDef . ruleRecommendations ,
420
435
} ) ;
421
436
}
422
437
@@ -438,36 +453,33 @@ export class TaskManagerServer {
438
453
public async updateTask (
439
454
projectId : string ,
440
455
taskId : string ,
441
- updates : { title ?: string ; description ?: string }
456
+ updates : {
457
+ title ?: string ;
458
+ description ?: string ;
459
+ toolRecommendations ?: string ;
460
+ ruleRecommendations ?: string ;
461
+ }
442
462
) {
443
- await this . loadTasks ( ) ;
444
- const proj = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
445
- if ( ! proj ) return { status : "error" , message : "Project not found" } ;
463
+ await this . ensureInitialized ( ) ;
464
+ const project = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
465
+ if ( ! project ) {
466
+ throw new Error ( `Project not found: ${ projectId } ` ) ;
467
+ }
446
468
447
- const task = proj . tasks . find ( ( t ) => t . id === taskId ) ;
448
- if ( ! task ) return { status : "error" , message : "Task not found" } ;
449
- if ( task . status === "done" )
450
- return { status : "error" , message : "Cannot update completed task" } ;
469
+ const taskIndex = project . tasks . findIndex ( ( t ) => t . id === taskId ) ;
470
+ if ( taskIndex === - 1 ) {
471
+ throw new Error ( `Task not found: ${ taskId } ` ) ;
472
+ }
451
473
452
- if ( updates . title ) task . title = updates . title ;
453
- if ( updates . description ) task . description = updates . description ;
474
+ // Update the task with the provided updates
475
+ project . tasks [ taskIndex ] = { ... project . tasks [ taskIndex ] , ... updates } ;
454
476
455
477
await this . saveTasks ( ) ;
456
-
457
- const progressTable = this . formatTaskProgressTable ( projectId ) ;
458
- return {
459
- status : "task_updated" ,
460
- message : `Task ${ taskId } has been updated.\n${ progressTable } ` ,
461
- task : {
462
- id : task . id ,
463
- title : task . title ,
464
- description : task . description ,
465
- } ,
466
- } ;
478
+ return project . tasks [ taskIndex ] ;
467
479
}
468
480
469
481
public async deleteTask ( projectId : string , taskId : string ) {
470
- await this . loadTasks ( ) ;
482
+ await this . ensureInitialized ( ) ;
471
483
const proj = this . data . projects . find ( ( p ) => p . projectId === projectId ) ;
472
484
if ( ! proj ) return { status : "error" , message : "Project not found" } ;
473
485
0 commit comments