@@ -15,6 +15,7 @@ use crate::experiments::api::{
1515} ;
1616use crate :: experiments:: { BaseExperimentInfo , ExperimentBuilder } ;
1717use crate :: log_queue:: { LogQueue , LogQueueConfig } ;
18+ use crate :: prompt:: { PromptBuilder , PromptFetchRequest , PromptFetchResponse , PromptFetcher } ;
1819use crate :: span:: SpanSubmitter ;
1920use crate :: types:: { ParentSpanInfo , SpanPayload } ;
2021
@@ -505,6 +506,13 @@ impl BraintrustClient {
505506 crate :: span:: SpanBuilder :: new ( submitter, token, org_id)
506507 }
507508
509+ /// Create a prompt builder with an explicit API token.
510+ ///
511+ /// Use this if you already have the token and don't want to use the login state.
512+ pub fn prompt_builder_with_credentials ( & self , token : impl Into < String > ) -> PromptBuilder < Self > {
513+ PromptBuilder :: new ( Arc :: new ( self . clone ( ) ) , token)
514+ }
515+
508516 /// Perform login synchronously.
509517 async fn perform_login ( & self , api_key : & str , org_name : Option < & str > ) -> Result < ( ) > {
510518 let login_url = self
@@ -910,6 +918,64 @@ impl ExperimentComparisonFetcher for BraintrustClient {
910918 }
911919}
912920
921+ #[ async_trait:: async_trait]
922+ impl PromptFetcher for BraintrustClient {
923+ async fn fetch_prompt (
924+ & self ,
925+ token : & str ,
926+ request : PromptFetchRequest ,
927+ ) -> Result < PromptFetchResponse > {
928+ let mut url = self
929+ . inner
930+ . api_url
931+ . join ( "v1/prompt" )
932+ . map_err ( |e| BraintrustError :: InvalidConfig ( e. to_string ( ) ) ) ?;
933+
934+ {
935+ let mut query = url. query_pairs_mut ( ) ;
936+ query. append_pair ( "slug" , & request. slug ) ;
937+ if let Some ( project_id) = & request. project_id {
938+ query. append_pair ( "project_id" , project_id) ;
939+ }
940+ if let Some ( project_name) = & request. project_name {
941+ query. append_pair ( "project_name" , project_name) ;
942+ }
943+ if let Some ( version) = & request. version {
944+ query. append_pair ( "version" , version) ;
945+ }
946+ if let Some ( environment) = & request. environment {
947+ query. append_pair ( "environment" , environment) ;
948+ }
949+ }
950+
951+ let response = self
952+ . inner
953+ . http_client
954+ . get ( url)
955+ . bearer_auth ( token)
956+ . send ( )
957+ . await
958+ . map_err ( |e| BraintrustError :: Network ( e. to_string ( ) ) ) ?;
959+
960+ if !response. status ( ) . is_success ( ) {
961+ let status = response. status ( ) ;
962+ let body = response. text ( ) . await . unwrap_or_default ( ) ;
963+ return Err ( BraintrustError :: Api {
964+ status : status. as_u16 ( ) ,
965+ message : body,
966+ } ) ;
967+ }
968+
969+ response
970+ . json :: < PromptFetchResponse > ( )
971+ . await
972+ . map_err ( |e| BraintrustError :: Api {
973+ status : 200 ,
974+ message : format ! ( "Failed to parse prompt response: {}" , e) ,
975+ } )
976+ }
977+ }
978+
913979#[ allow( dead_code) ]
914980#[ derive( Debug , Default ) ]
915981struct MutableSpanEvent {
0 commit comments