@@ -11,6 +11,8 @@ import {
1111import { TaskManager } from "../server/TaskManager.js" ;
1212import { createError , normalizeError } from "../utils/errors.js" ;
1313import { formatCliError } from "./errors.js" ;
14+ import fs from "fs/promises" ;
15+ import type { StandardResponse } from "../types/index.js" ;
1416
1517const program = new Command ( ) ;
1618
@@ -396,7 +398,12 @@ program
396398 } else {
397399 console . log ( chalk . yellow ( `\nNo tasks found${ filterState ? ` matching state '${ filterState } '` : '' } in project ${ projectId } .` ) ) ;
398400 }
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+ }
400407 // Handle ProjectNotFound specifically if desired, otherwise let generic handler catch
401408 const normalized = normalizeError ( error ) ;
402409 if ( normalized . code === ErrorCode . ProjectNotFound ) {
@@ -457,8 +464,12 @@ program
457464 } else {
458465 console . log ( chalk . yellow ( ' No tasks in this project.' ) ) ;
459466 }
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+ }
462473 }
463474 }
464475 }
@@ -469,4 +480,92 @@ program
469480 }
470481 } ) ;
471482
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+
472571program . parse ( process . argv ) ;
0 commit comments