@@ -9,8 +9,14 @@ enum Command {
99 Doctor ,
1010 ProvidersList ,
1111 ContextInspect ,
12- ContextPack { task : String } ,
13- Ask { dry_run : bool , prompt : String } ,
12+ ContextPack {
13+ task : String ,
14+ } ,
15+ Ask {
16+ provider : Option < String > ,
17+ dry_run : bool ,
18+ prompt : String ,
19+ } ,
1420}
1521
1622#[ derive( Serialize , Deserialize , Debug , Clone ) ]
8793 1
8894 }
8995 } ,
90- Ok ( Command :: Ask { dry_run, prompt } ) => match handle_ask ( dry_run, & prompt) {
96+ Ok ( Command :: Ask {
97+ provider,
98+ dry_run,
99+ prompt,
100+ } ) => match handle_ask ( provider. as_deref ( ) , dry_run, & prompt) {
91101 Ok ( _) => 0 ,
92102 Err ( e) => {
93103 eprintln ! ( "error: {e}" ) ;
@@ -189,22 +199,53 @@ fn parse(argv: &[String]) -> Result<Command, String> {
189199 "ask" => {
190200 if argv. len ( ) < 3 {
191201 return Err (
192- "missing arguments for 'ask'. Usage: ctxt ask --dry-run \" <prompt>\" "
202+ "missing arguments for 'ask'. Usage: ctxt ask --dry-run \" <prompt>\" or ctxt ask --provider <provider> \" <prompt> \" "
193203 . to_string ( ) ,
194204 ) ;
195205 }
196- if argv[ 1 ] != "--dry-run" {
197- return Err ( format ! (
198- "unexpected option '{}' for 'ask'. Expected '--dry-run'" ,
199- argv[ 1 ]
200- ) ) ;
206+
207+ let mut provider = None ;
208+ let mut dry_run = false ;
209+ let mut prompt = String :: new ( ) ;
210+
211+ let mut i = 1 ;
212+ while i < argv. len ( ) {
213+ match argv[ i] . as_str ( ) {
214+ "--dry-run" => {
215+ dry_run = true ;
216+ i += 1 ;
217+ }
218+ "--provider" => {
219+ if i + 1 >= argv. len ( ) {
220+ return Err ( "missing provider name after --provider" . to_string ( ) ) ;
221+ }
222+ provider = Some ( argv[ i + 1 ] . clone ( ) ) ;
223+ i += 2 ;
224+ }
225+ other => {
226+ if other. starts_with ( '-' ) {
227+ return Err ( format ! ( "unsupported option '{other}' for 'ask'" ) ) ;
228+ }
229+ if !prompt. is_empty ( ) {
230+ return Err ( format ! ( "unexpected argument '{other}' for 'ask'" ) ) ;
231+ }
232+ prompt = other. to_string ( ) ;
233+ i += 1 ;
234+ }
235+ }
201236 }
202- let prompt = argv[ 2 ] . clone ( ) ;
203- if argv. len ( ) > 3 {
204- return Err ( format ! ( "unexpected argument '{}' for 'ask'" , argv[ 3 ] ) ) ;
237+
238+ if prompt. is_empty ( ) {
239+ return Err ( "missing prompt for 'ask'" . to_string ( ) ) ;
240+ }
241+
242+ if !dry_run && provider. is_none ( ) {
243+ return Err ( "must specify either --dry-run or --provider <provider>" . to_string ( ) ) ;
205244 }
245+
206246 Ok ( Command :: Ask {
207- dry_run : true ,
247+ provider,
248+ dry_run,
208249 prompt,
209250 } )
210251 }
@@ -410,11 +451,7 @@ fn handle_context_pack(task: &str) -> Result<(), String> {
410451 Ok ( ( ) )
411452}
412453
413- fn handle_ask ( dry_run : bool , prompt : & str ) -> Result < ( ) , String > {
414- if !dry_run {
415- return Err ( "Only dry-run is supported. Use --dry-run flag." . to_string ( ) ) ;
416- }
417-
454+ fn handle_ask ( provider : Option < & str > , dry_run : bool , prompt : & str ) -> Result < ( ) , String > {
418455 let cp = build_context_pack ( prompt) ?;
419456 std:: fs:: create_dir_all ( ".comptext" )
420457 . map_err ( |e| format ! ( "failed to create .comptext directory: {e}" ) ) ?;
@@ -430,7 +467,7 @@ fn handle_ask(dry_run: bool, prompt: &str) -> Result<(), String> {
430467 cp. rendered_context
431468 ) ;
432469 let request = ModelRequest {
433- provider : "dummy" . to_string ( ) ,
470+ provider : provider . unwrap_or ( "dummy" ) . to_string ( ) ,
434471 model : "dummy-model" . to_string ( ) ,
435472 messages : vec ! [
436473 Message {
@@ -450,10 +487,32 @@ fn handle_ask(dry_run: bool, prompt: &str) -> Result<(), String> {
450487 std:: fs:: write ( ".comptext/model_request.latest.json" , req_json)
451488 . map_err ( |e| format ! ( "failed to write model request: {e}" ) ) ?;
452489
453- println ! ( "Dry-run successful." ) ;
454- println ! ( "Context Pack: .comptext/context_pack.latest.json" ) ;
455- println ! ( "Model Request: .comptext/model_request.latest.json" ) ;
456- Ok ( ( ) )
490+ if dry_run {
491+ println ! ( "Dry-run successful." ) ;
492+ println ! ( "Context Pack: .comptext/context_pack.latest.json" ) ;
493+ println ! ( "Model Request: .comptext/model_request.latest.json" ) ;
494+ return Ok ( ( ) ) ;
495+ }
496+
497+ let p_name = provider. ok_or_else ( || "provider is required for live execution" . to_string ( ) ) ?;
498+ match p_name {
499+ "dummy" => {
500+ use crate :: provider:: { DummyProvider , Provider } ;
501+ let prov = DummyProvider ;
502+ let response = prov. execute ( & request) ?;
503+
504+ let resp_json = serde_json:: to_string_pretty ( & response)
505+ . map_err ( |e| format ! ( "failed to serialize model response: {e}" ) ) ?;
506+
507+ std:: fs:: write ( ".comptext/model_response.latest.json" , resp_json)
508+ . map_err ( |e| format ! ( "failed to write model response: {e}" ) ) ?;
509+
510+ println ! ( "Response from {} provider:" , prov. name( ) ) ;
511+ println ! ( "{}" , response. content) ;
512+ Ok ( ( ) )
513+ }
514+ other => Err ( format ! ( "unsupported provider '{other}'" ) ) ,
515+ }
457516}
458517
459518#[ cfg( test) ]
@@ -519,12 +578,30 @@ mod tests {
519578 assert_eq ! (
520579 parse( & s( & [ "ask" , "--dry-run" , "How do I test this repo?" ] ) ) ,
521580 Ok ( Command :: Ask {
581+ provider: None ,
522582 dry_run: true ,
523583 prompt: "How do I test this repo?" . to_string( )
524584 } )
525585 ) ;
526586 }
527587
588+ #[ test]
589+ fn parses_ask_provider ( ) {
590+ assert_eq ! (
591+ parse( & s( & [
592+ "ask" ,
593+ "--provider" ,
594+ "dummy" ,
595+ "How do I test this repo?"
596+ ] ) ) ,
597+ Ok ( Command :: Ask {
598+ provider: Some ( "dummy" . to_string( ) ) ,
599+ dry_run: false ,
600+ prompt: "How do I test this repo?" . to_string( )
601+ } )
602+ ) ;
603+ }
604+
528605 #[ test]
529606 fn rejects_unknown_command ( ) {
530607 assert ! ( parse( & s( & [ "unknown" ] ) ) . is_err( ) ) ;
0 commit comments