@@ -9,6 +9,7 @@ use crate::auth::AuthMode;
99use crate :: error:: EnvVarError ;
1010use codex_api:: Provider as ApiProvider ;
1111use codex_api:: provider:: RetryConfig as ApiRetryConfig ;
12+ use codex_protocol:: config_types:: ModelProviderAuthInfo ;
1213use http:: HeaderMap ;
1314use http:: header:: HeaderName ;
1415use http:: header:: HeaderValue ;
@@ -86,6 +87,9 @@ pub struct ModelProviderInfo {
8687 /// this may be necessary when using this programmatically.
8788 pub experimental_bearer_token : Option < String > ,
8889
90+ /// Command-backed bearer-token configuration for this provider.
91+ pub auth : Option < ModelProviderAuthInfo > ,
92+
8993 /// Which wire protocol this provider expects.
9094 #[ serde( default ) ]
9195 pub wire_api : WireApi ,
@@ -130,6 +134,36 @@ pub struct ModelProviderInfo {
130134}
131135
132136impl ModelProviderInfo {
137+ pub ( crate ) fn validate ( & self ) -> std:: result:: Result < ( ) , String > {
138+ let Some ( auth) = self . auth . as_ref ( ) else {
139+ return Ok ( ( ) ) ;
140+ } ;
141+
142+ if auth. command . trim ( ) . is_empty ( ) {
143+ return Err ( "provider auth.command must not be empty" . to_string ( ) ) ;
144+ }
145+
146+ let mut conflicts = Vec :: new ( ) ;
147+ if self . env_key . is_some ( ) {
148+ conflicts. push ( "env_key" ) ;
149+ }
150+ if self . experimental_bearer_token . is_some ( ) {
151+ conflicts. push ( "experimental_bearer_token" ) ;
152+ }
153+ if self . requires_openai_auth {
154+ conflicts. push ( "requires_openai_auth" ) ;
155+ }
156+
157+ if conflicts. is_empty ( ) {
158+ Ok ( ( ) )
159+ } else {
160+ Err ( format ! (
161+ "provider auth cannot be combined with {}" ,
162+ conflicts. join( ", " )
163+ ) )
164+ }
165+ }
166+
133167 fn build_header_map ( & self ) -> crate :: error:: Result < HeaderMap > {
134168 let capacity = self . http_headers . as_ref ( ) . map_or ( 0 , HashMap :: len)
135169 + self . env_http_headers . as_ref ( ) . map_or ( 0 , HashMap :: len) ;
@@ -246,6 +280,7 @@ impl ModelProviderInfo {
246280 env_key : None ,
247281 env_key_instructions : None ,
248282 experimental_bearer_token : None ,
283+ auth : None ,
249284 wire_api : WireApi :: Responses ,
250285 query_params : None ,
251286 http_headers : Some (
@@ -277,6 +312,10 @@ impl ModelProviderInfo {
277312 pub fn is_openai ( & self ) -> bool {
278313 self . name == OPENAI_PROVIDER_NAME
279314 }
315+
316+ pub ( crate ) fn has_command_auth ( & self ) -> bool {
317+ self . auth . is_some ( )
318+ }
280319}
281320
282321pub const DEFAULT_LMSTUDIO_PORT : u16 = 1234 ;
@@ -338,6 +377,7 @@ pub fn create_oss_provider_with_base_url(base_url: &str, wire_api: WireApi) -> M
338377 env_key : None ,
339378 env_key_instructions : None ,
340379 experimental_bearer_token : None ,
380+ auth : None ,
341381 wire_api,
342382 query_params : None ,
343383 http_headers : None ,
0 commit comments