@@ -2,6 +2,7 @@ use crate::spawn::CODEX_SANDBOX_ENV_VAR;
22use reqwest:: header:: HeaderValue ;
33use std:: sync:: LazyLock ;
44use std:: sync:: Mutex ;
5+ use std:: sync:: OnceLock ;
56
67/// Set this to add a suffix to the User-Agent string.
78///
@@ -26,8 +27,15 @@ pub struct Originator {
2627 pub value : String ,
2728 pub header_value : HeaderValue ,
2829}
30+ static ORIGINATOR : OnceLock < Originator > = OnceLock :: new ( ) ;
2931
30- pub static ORIGINATOR : LazyLock < Originator > = LazyLock :: new ( || {
32+ #[ derive( Debug ) ]
33+ pub enum SetOriginatorError {
34+ InvalidHeaderValue ,
35+ AlreadyInitialized ,
36+ }
37+
38+ fn init_originator_from_env ( ) -> Originator {
3139 let default = "codex_cli_rs" ;
3240 let value = std:: env:: var ( CODEX_INTERNAL_ORIGINATOR_OVERRIDE_ENV_VAR )
3341 . unwrap_or_else ( |_| default. to_string ( ) ) ;
@@ -45,14 +53,34 @@ pub static ORIGINATOR: LazyLock<Originator> = LazyLock::new(|| {
4553 }
4654 }
4755 }
48- } ) ;
56+ }
57+
58+ fn build_originator ( value : String ) -> Result < Originator , SetOriginatorError > {
59+ let header_value =
60+ HeaderValue :: from_str ( & value) . map_err ( |_| SetOriginatorError :: InvalidHeaderValue ) ?;
61+ Ok ( Originator {
62+ value,
63+ header_value,
64+ } )
65+ }
66+
67+ pub fn set_default_originator ( value : & str ) -> Result < ( ) , SetOriginatorError > {
68+ let originator = build_originator ( value. to_string ( ) ) ?;
69+ ORIGINATOR
70+ . set ( originator)
71+ . map_err ( |_| SetOriginatorError :: AlreadyInitialized )
72+ }
73+
74+ pub fn originator ( ) -> & ' static Originator {
75+ ORIGINATOR . get_or_init ( init_originator_from_env)
76+ }
4977
5078pub fn get_codex_user_agent ( ) -> String {
5179 let build_version = env ! ( "CARGO_PKG_VERSION" ) ;
5280 let os_info = os_info:: get ( ) ;
5381 let prefix = format ! (
5482 "{}/{build_version} ({} {}; {}) {}" ,
55- ORIGINATOR . value. as_str( ) ,
83+ originator ( ) . value. as_str( ) ,
5684 os_info. os_type( ) ,
5785 os_info. version( ) ,
5886 os_info. architecture( ) . unwrap_or( "unknown" ) ,
@@ -100,7 +128,7 @@ fn sanitize_user_agent(candidate: String, fallback: &str) -> String {
100128 tracing:: warn!(
101129 "Falling back to default Codex originator because base user agent string is invalid"
102130 ) ;
103- ORIGINATOR . value . clone ( )
131+ originator ( ) . value . clone ( )
104132 }
105133}
106134
@@ -109,7 +137,7 @@ pub fn create_client() -> reqwest::Client {
109137 use reqwest:: header:: HeaderMap ;
110138
111139 let mut headers = HeaderMap :: new ( ) ;
112- headers. insert ( "originator" , ORIGINATOR . header_value . clone ( ) ) ;
140+ headers. insert ( "originator" , originator ( ) . header_value . clone ( ) ) ;
113141 let ua = get_codex_user_agent ( ) ;
114142
115143 let mut builder = reqwest:: Client :: builder ( )
0 commit comments