@@ -11,6 +11,8 @@ import {
11
11
import { TaskManager } from "../server/TaskManager.js" ;
12
12
import { createError , normalizeError } from "../utils/errors.js" ;
13
13
import { formatCliError } from "./errors.js" ;
14
+ import fs from "fs/promises" ;
15
+ import type { StandardResponse } from "../types/index.js" ;
14
16
15
17
const program = new Command ( ) ;
16
18
@@ -396,7 +398,12 @@ program
396
398
} else {
397
399
console . log ( chalk . yellow ( `\nNo tasks found${ filterState ? ` matching state '${ filterState } '` : '' } in project ${ projectId } .` ) ) ;
398
400
}
399
- } catch ( error ) {
401
+ } catch ( error : unknown ) {
402
+ if ( error instanceof Error ) {
403
+ console . error ( chalk . red ( `Error fetching details for project ${ projectId } : ${ error . message } ` ) ) ;
404
+ } else {
405
+ console . error ( chalk . red ( `Error fetching details for project ${ projectId } : Unknown error` ) ) ;
406
+ }
400
407
// Handle ProjectNotFound specifically if desired, otherwise let generic handler catch
401
408
const normalized = normalizeError ( error ) ;
402
409
if ( normalized . code === ErrorCode . ProjectNotFound ) {
@@ -457,8 +464,12 @@ program
457
464
} else {
458
465
console . log ( chalk . yellow ( ' No tasks in this project.' ) ) ;
459
466
}
460
- } catch ( error ) {
461
- console . error ( chalk . red ( `Error fetching details for project ${ pSummary . projectId } : ${ formatCliError ( normalizeError ( error ) ) } ` ) ) ;
467
+ } catch ( error : unknown ) {
468
+ if ( error instanceof Error ) {
469
+ console . error ( chalk . red ( `Error fetching details for project ${ pSummary . projectId } : ${ error . message } ` ) ) ;
470
+ } else {
471
+ console . error ( chalk . red ( `Error fetching details for project ${ pSummary . projectId } : Unknown error` ) ) ;
472
+ }
462
473
}
463
474
}
464
475
}
@@ -469,4 +480,92 @@ program
469
480
}
470
481
} ) ;
471
482
483
+ program
484
+ . command ( "generate-plan" )
485
+ . description ( "Generate a project plan using an LLM" )
486
+ . requiredOption ( "--prompt <text>" , "Prompt text to feed to the LLM" )
487
+ . option ( "--model <model>" , "LLM model to use" , "gpt-4-turbo" )
488
+ . option ( "--provider <provider>" , "LLM provider to use (openai, google, or deepseek)" , "openai" )
489
+ . option ( "--attachment <file>" , "File to attach as context (can be specified multiple times)" , collect , [ ] )
490
+ . action ( async ( options ) => {
491
+ try {
492
+ console . log ( chalk . blue ( `Generating project plan from prompt...` ) ) ;
493
+
494
+ // Read attachment files if provided
495
+ const attachments : string [ ] = [ ] ;
496
+ for ( const file of options . attachment ) {
497
+ try {
498
+ const content = await fs . readFile ( file , 'utf-8' ) ;
499
+ attachments . push ( content ) ;
500
+ } catch ( error : unknown ) {
501
+ if ( error instanceof Error ) {
502
+ console . error ( chalk . yellow ( `Warning: Could not read attachment file ${ chalk . bold ( file ) } : ${ error . message } ` ) ) ;
503
+ } else {
504
+ console . error ( chalk . yellow ( `Warning: Could not read attachment file ${ chalk . bold ( file ) } : Unknown error` ) ) ;
505
+ }
506
+ }
507
+ }
508
+
509
+ // Call the generateProjectPlan method
510
+ const response = await taskManager . generateProjectPlan ( {
511
+ prompt : options . prompt ,
512
+ provider : options . provider ,
513
+ model : options . model ,
514
+ attachments,
515
+ } ) ;
516
+
517
+ if ( 'error' in response ) {
518
+ throw response . error ;
519
+ }
520
+
521
+ if ( response . status !== "success" ) {
522
+ throw createError (
523
+ ErrorCode . InvalidResponseFormat ,
524
+ "Unexpected response format from TaskManager"
525
+ ) ;
526
+ }
527
+
528
+ const data = response . data as {
529
+ projectId : string ;
530
+ totalTasks: number ;
531
+ tasks: Array < {
532
+ id : string ;
533
+ title: string ;
534
+ description: string ;
535
+ } > ;
536
+ message ? : string ;
537
+ } ;
538
+
539
+ // Display the results
540
+ console . log ( chalk . green ( `✅ Project plan generated successfully!` ) ) ;
541
+ console . log ( chalk . cyan ( '\n📋 Project details:' ) ) ;
542
+ console . log ( ` - ${ chalk . bold ( 'Project ID:' ) } ${ data . projectId } ` ) ;
543
+ console . log ( ` - ${ chalk . bold ( 'Total Tasks:' ) } ${ data . totalTasks } ` ) ;
544
+
545
+ console . log ( chalk . cyan ( '\n📝 Tasks:' ) ) ;
546
+ data . tasks . forEach ( ( task ) => {
547
+ console . log ( `\n ${ chalk . bold ( task . id ) } :` ) ;
548
+ console . log ( ` Title: ${ task . title } ` ) ;
549
+ console . log ( ` Description: ${ task . description } ` ) ;
550
+ } ) ;
551
+
552
+ if ( data . message ) {
553
+ console . log ( `\n${ data . message } ` ) ;
554
+ }
555
+ } catch ( err : unknown ) {
556
+ if ( err instanceof Error ) {
557
+ console . error ( chalk . yellow ( `Warning: ${ err . message } ` ) ) ;
558
+ } else {
559
+ const normalized = normalizeError ( err ) ;
560
+ console . error ( chalk . red ( formatCliError ( normalized ) ) ) ;
561
+ }
562
+ process . exit ( 1 ) ;
563
+ }
564
+ } ) ;
565
+
566
+ // Helper function for collecting multiple values for the same option
567
+ function collect ( value : string , previous : string [ ] ) {
568
+ return previous . concat ( [ value ] ) ;
569
+ }
570
+
472
571
program . parse ( process . argv ) ;
0 commit comments