@@ -82,9 +82,15 @@ impl ExecCli {
8282
8383 // Read from file if specified
8484 if let Some ( ref file_path) = self . file {
85- let content = tokio:: fs:: read_to_string ( file_path)
85+ let resolved_file_path = resolve_prompt_file_path ( file_path, self . cwd . as_ref ( ) ) ;
86+ let content = tokio:: fs:: read_to_string ( & resolved_file_path)
8687 . await
87- . with_context ( || format ! ( "Failed to read prompt file: {}" , file_path. display( ) ) ) ?;
88+ . with_context ( || {
89+ format ! (
90+ "Failed to read prompt file: {}" ,
91+ resolved_file_path. display( )
92+ )
93+ } ) ?;
8894 prompt. push_str ( & content) ;
8995 }
9096
@@ -852,3 +858,46 @@ impl ExecCli {
852858 Ok ( ( ) )
853859 }
854860}
861+
862+ fn resolve_prompt_file_path ( file_path : & std:: path:: Path , cwd : Option < & PathBuf > ) -> PathBuf {
863+ if file_path. is_absolute ( ) {
864+ return file_path. to_path_buf ( ) ;
865+ }
866+
867+ cwd. map_or_else ( || file_path. to_path_buf ( ) , |cwd| cwd. join ( file_path) )
868+ }
869+
870+ #[ cfg( test) ]
871+ mod tests {
872+ use super :: resolve_prompt_file_path;
873+ use std:: path:: { Path , PathBuf } ;
874+
875+ #[ test]
876+ fn resolves_relative_prompt_file_against_cwd ( ) {
877+ let cwd = PathBuf :: from ( "/tmp/cortex_test/nested" ) ;
878+
879+ assert_eq ! (
880+ resolve_prompt_file_path( Path :: new( "script.sh" ) , Some ( & cwd) ) ,
881+ cwd. join( "script.sh" )
882+ ) ;
883+ }
884+
885+ #[ test]
886+ fn leaves_relative_prompt_file_relative_without_cwd ( ) {
887+ assert_eq ! (
888+ resolve_prompt_file_path( Path :: new( "script.sh" ) , None ) ,
889+ PathBuf :: from( "script.sh" )
890+ ) ;
891+ }
892+
893+ #[ test]
894+ fn leaves_absolute_prompt_file_unchanged ( ) {
895+ let path = if cfg ! ( windows) {
896+ PathBuf :: from ( r"C:\tmp\script.sh" )
897+ } else {
898+ PathBuf :: from ( "/tmp/script.sh" )
899+ } ;
900+
901+ assert_eq ! ( resolve_prompt_file_path( & path, None ) , path) ;
902+ }
903+ }
0 commit comments