@@ -121,11 +121,7 @@ pub enum Transport {
121121 #[ default]
122122 Default ,
123123 /// Communicate over stdin/stdout pipes (default).
124- Stdio {
125- /// Environment passed to the child process, replacing its inherited
126- /// environment. SDK-managed variables are applied afterward.
127- env : Option < Vec < ( OsString , OsString ) > > ,
128- } ,
124+ Stdio ,
129125 /// Host the runtime in-process over FFI (no child process).
130126 ///
131127 /// Loads the native runtime library next to the resolved CLI entrypoint
@@ -148,9 +144,6 @@ pub enum Transport {
148144 /// the CLI, the SDK auto-generates a 128-bit hex token so the
149145 /// loopback listener is safe by default.
150146 connection_token : Option < String > ,
151- /// Environment passed to the child process, replacing its inherited
152- /// environment. SDK-managed variables are applied afterward.
153- env : Option < Vec < ( OsString , OsString ) > > ,
154147 } ,
155148 /// Connect to an already-running CLI server (no process spawning).
156149 External {
@@ -240,20 +233,11 @@ pub struct ClientOptions {
240233 pub prefix_args : Vec < OsString > ,
241234 /// Working directory for the CLI process.
242235 ///
243- /// `None` uses the host process's current directory. Setting this option is
244- /// not supported with [`Transport::InProcess`].
245- pub working_directory : Option < PathBuf > ,
236+ /// Setting this option is not supported with [`Transport::InProcess`].
237+ pub working_directory : PathBuf ,
246238 /// Environment variables set on the child process.
247- #[ deprecated(
248- since = "0.1.0" ,
249- note = "set `env` on `Transport::Stdio` or `Transport::Tcp` instead"
250- ) ]
251239 pub env : Vec < ( OsString , OsString ) > ,
252240 /// Environment variable names to remove from the child process.
253- #[ deprecated(
254- since = "0.1.0" ,
255- note = "use a transport-level replacement environment that omits these variables"
256- ) ]
257241 pub env_remove : Vec < OsString > ,
258242 /// Extra CLI flags appended after the transport-specific arguments.
259243 pub extra_args : Vec < String > ,
@@ -362,7 +346,6 @@ pub struct ClientOptions {
362346 pub mode : ClientMode ,
363347}
364348
365- #[ allow( deprecated) ]
366349impl std:: fmt:: Debug for ClientOptions {
367350 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
368351 f. debug_struct ( "ClientOptions" )
@@ -627,13 +610,12 @@ impl TelemetryConfig {
627610 }
628611}
629612
630- #[ allow( deprecated) ]
631613impl Default for ClientOptions {
632614 fn default ( ) -> Self {
633615 Self {
634616 program : CliProgram :: Resolve ,
635617 prefix_args : Vec :: new ( ) ,
636- working_directory : None ,
618+ working_directory : PathBuf :: new ( ) ,
637619 env : Vec :: new ( ) ,
638620 env_remove : Vec :: new ( ) ,
639621 extra_args : Vec :: new ( ) ,
@@ -656,7 +638,6 @@ impl Default for ClientOptions {
656638 }
657639}
658640
659- #[ allow( deprecated) ]
660641impl ClientOptions {
661642 /// Construct a new [`ClientOptions`] with default values.
662643 ///
@@ -695,15 +676,11 @@ impl ClientOptions {
695676
696677 /// Working directory for the CLI process.
697678 pub fn with_cwd ( mut self , cwd : impl Into < PathBuf > ) -> Self {
698- self . working_directory = Some ( cwd. into ( ) ) ;
679+ self . working_directory = cwd. into ( ) ;
699680 self
700681 }
701682
702683 /// Environment variables to set on the child process.
703- #[ deprecated(
704- since = "0.1.0" ,
705- note = "set `env` on `Transport::Stdio` or `Transport::Tcp` instead"
706- ) ]
707684 pub fn with_env < I , K , V > ( mut self , env : I ) -> Self
708685 where
709686 I : IntoIterator < Item = ( K , V ) > ,
@@ -715,10 +692,6 @@ impl ClientOptions {
715692 }
716693
717694 /// Environment variable names to remove from the child process.
718- #[ deprecated(
719- since = "0.1.0" ,
720- note = "use a transport-level replacement environment that omits these variables"
721- ) ]
722695 pub fn with_env_remove < I , S > ( mut self , names : I ) -> Self
723696 where
724697 I : IntoIterator < Item = S > ,
@@ -910,7 +883,6 @@ fn generate_connection_token() -> String {
910883const DEFAULT_CONNECTION_ENV_VAR : & str = "COPILOT_SDK_DEFAULT_CONNECTION" ;
911884
912885/// Resolve a transport override from [`DEFAULT_CONNECTION_ENV_VAR`].
913- #[ allow( deprecated) ]
914886fn resolve_default_transport ( options : & ClientOptions ) -> Result < Transport > {
915887 let configured = options
916888 . env
@@ -926,10 +898,8 @@ fn resolve_default_transport(options: &ClientOptions) -> Result<Transport> {
926898
927899fn resolve_default_transport_value ( value : Option < & str > ) -> Result < Transport > {
928900 match value {
929- None => Ok ( Transport :: Stdio { env : None } ) ,
930- Some ( v) if v. is_empty ( ) || v. eq_ignore_ascii_case ( "stdio" ) => {
931- Ok ( Transport :: Stdio { env : None } )
932- }
901+ None => Ok ( Transport :: Stdio ) ,
902+ Some ( v) if v. is_empty ( ) || v. eq_ignore_ascii_case ( "stdio" ) => Ok ( Transport :: Stdio ) ,
933903 Some ( v) if v. eq_ignore_ascii_case ( "inprocess" ) => Ok ( Transport :: InProcess ) ,
934904 Some ( v) => Err ( Error :: with_message (
935905 ErrorKind :: InvalidConfig ,
@@ -942,9 +912,8 @@ fn resolve_default_transport_value(value: Option<&str>) -> Result<Transport> {
942912}
943913
944914#[ cfg( any( feature = "bundled-in-process" , test) ) ]
945- #[ allow( deprecated) ]
946915fn validate_inprocess_options ( options : & ClientOptions ) -> Result < ( ) > {
947- let unsupported = if options. working_directory . is_some ( ) {
916+ let unsupported = if ! options. working_directory . as_os_str ( ) . is_empty ( ) {
948917 Some ( "working_directory" )
949918 } else if !options. env . is_empty ( ) {
950919 Some ( "env" )
@@ -973,23 +942,6 @@ fn validate_inprocess_options(options: &ClientOptions) -> Result<()> {
973942 Ok ( ( ) )
974943}
975944
976- #[ allow( deprecated) ]
977- fn validate_transport_environment ( options : & ClientOptions ) -> Result < ( ) > {
978- let transport_env_is_set = matches ! (
979- & options. transport,
980- Transport :: Stdio { env: Some ( _) } | Transport :: Tcp { env: Some ( _) , .. }
981- ) ;
982- if transport_env_is_set && ( !options. env . is_empty ( ) || !options. env_remove . is_empty ( ) ) {
983- return Err ( Error :: with_message (
984- ErrorKind :: InvalidConfig ,
985- "set child-process environment variables via either the transport-level `env` \
986- option or the deprecated ClientOptions::env/ClientOptions::env_remove options, \
987- not both",
988- ) ) ;
989- }
990- Ok ( ( ) )
991- }
992-
993945/// Connection to a GitHub Copilot CLI server (stdio, TCP, or external).
994946///
995947/// Cheaply cloneable — cloning shares the underlying connection.
@@ -1064,7 +1016,6 @@ impl Client {
10641016 if matches ! ( options. transport, Transport :: Default ) {
10651017 options. transport = resolve_default_transport ( & options) ?;
10661018 }
1067- validate_transport_environment ( & options) ?;
10681019 if matches ! ( options. transport, Transport :: InProcess ) {
10691020 #[ cfg( not( feature = "bundled-in-process" ) ) ]
10701021 {
@@ -1132,7 +1083,7 @@ impl Client {
11321083 // default.
11331084 let effective_connection_token: Option < String > = match & mut options. transport {
11341085 Transport :: Default => unreachable ! ( "default transport resolved above" ) ,
1135- Transport :: Stdio { .. } | Transport :: InProcess => None ,
1086+ Transport :: Stdio | Transport :: InProcess => None ,
11361087 Transport :: Tcp {
11371088 connection_token, ..
11381089 } => Some (
@@ -1176,10 +1127,14 @@ impl Client {
11761127 resolved
11771128 }
11781129 } ;
1179- let working_directory = options
1180- . working_directory
1181- . clone ( )
1182- . unwrap_or_else ( || std:: env:: current_dir ( ) . unwrap_or_else ( |_| PathBuf :: from ( "." ) ) ) ;
1130+ let working_directory = {
1131+ let cwd = options. working_directory . clone ( ) ;
1132+ if cwd. as_os_str ( ) . is_empty ( ) {
1133+ std:: env:: current_dir ( ) . unwrap_or_else ( |_| PathBuf :: from ( "." ) )
1134+ } else {
1135+ cwd
1136+ }
1137+ } ;
11831138
11841139 let client = match options. transport {
11851140 Transport :: Default => unreachable ! ( "default transport resolved above" ) ,
@@ -1215,7 +1170,6 @@ impl Client {
12151170 Transport :: Tcp {
12161171 port,
12171172 connection_token : _,
1218- env : _,
12191173 } => {
12201174 let ( mut child, actual_port) =
12211175 Self :: spawn_tcp ( & program, & options, & working_directory, port) . await ?;
@@ -1242,7 +1196,7 @@ impl Client {
12421196 options. mode ,
12431197 ) ?
12441198 }
1245- Transport :: Stdio { env : _ } => {
1199+ Transport :: Stdio => {
12461200 let mut child = Self :: spawn_stdio ( & program, & options, & working_directory) ?;
12471201 let stdin = child. stdin . take ( ) . expect ( "stdin is piped" ) ;
12481202 let stdout = child. stdout . take ( ) . expect ( "stdout is piped" ) ;
@@ -1580,23 +1534,18 @@ impl Client {
15801534 } ) ;
15811535 }
15821536
1583- #[ allow( deprecated) ]
15841537 fn build_command ( program : & Path , options : & ClientOptions , working_directory : & Path ) -> Command {
15851538 let mut command = Command :: new ( program) ;
15861539 for arg in & options. prefix_args {
15871540 command. arg ( arg) ;
15881541 }
1589- let transport_env = match & options. transport {
1590- Transport :: Stdio { env } | Transport :: Tcp { env, .. } => env. as_ref ( ) ,
1591- _ => None ,
1592- } ;
1593- if let Some ( env) = transport_env {
1594- command. env_clear ( ) ;
1595- command. envs ( env. iter ( ) . map ( |( key, value) | ( key, value) ) ) ;
1596- }
1542+ // Inject the SDK auth token first so explicit `env` / `env_remove`
1543+ // entries can override or strip it.
15971544 if let Some ( token) = & options. github_token {
15981545 command. env ( "COPILOT_SDK_AUTH_TOKEN" , token) ;
15991546 }
1547+ // Inject telemetry env vars before user env so callers can still
1548+ // override individual variables via `options.env`.
16001549 if let Some ( telemetry) = & options. telemetry {
16011550 command. env ( "COPILOT_OTEL_ENABLED" , "true" ) ;
16021551 if let Some ( endpoint) = & telemetry. otlp_endpoint {
@@ -1636,13 +1585,11 @@ impl Client {
16361585 {
16371586 command. env ( "COPILOT_CONNECTION_TOKEN" , token) ;
16381587 }
1639- if transport_env. is_none ( ) {
1640- for ( key, value) in & options. env {
1641- command. env ( key, value) ;
1642- }
1643- for key in & options. env_remove {
1644- command. env_remove ( key) ;
1645- }
1588+ for ( key, value) in & options. env {
1589+ command. env ( key, value) ;
1590+ }
1591+ for key in & options. env_remove {
1592+ command. env_remove ( key) ;
16461593 }
16471594 command
16481595 . current_dir ( working_directory)
@@ -2486,7 +2433,6 @@ impl Drop for ClientInner {
24862433}
24872434
24882435#[ cfg( test) ]
2489- #[ allow( deprecated) ]
24902436mod tests {
24912437 use super :: * ;
24922438
@@ -2530,7 +2476,7 @@ mod tests {
25302476 . with_enable_remote_sessions ( true ) ;
25312477 assert ! ( matches!( opts. program, CliProgram :: Path ( _) ) ) ;
25322478 assert_eq ! ( opts. prefix_args, vec![ std:: ffi:: OsString :: from( "node" ) ] ) ;
2533- assert_eq ! ( opts. working_directory, Some ( PathBuf :: from( "/tmp" ) ) ) ;
2479+ assert_eq ! ( opts. working_directory, PathBuf :: from( "/tmp" ) ) ;
25342480 assert_eq ! (
25352481 opts. env,
25362482 vec![ (
@@ -2551,11 +2497,11 @@ mod tests {
25512497 fn default_transport_values_resolve_without_process_state ( ) {
25522498 assert ! ( matches!(
25532499 resolve_default_transport_value( None ) . unwrap( ) ,
2554- Transport :: Stdio { env : None }
2500+ Transport :: Stdio
25552501 ) ) ;
25562502 assert ! ( matches!(
25572503 resolve_default_transport_value( Some ( "stdio" ) ) . unwrap( ) ,
2558- Transport :: Stdio { env : None }
2504+ Transport :: Stdio
25592505 ) ) ;
25602506 assert ! ( matches!(
25612507 resolve_default_transport_value( Some ( "INPROCESS" ) ) . unwrap( ) ,
@@ -2593,49 +2539,6 @@ mod tests {
25932539 assert ! ( validate_inprocess_options( & options) . is_ok( ) ) ;
25942540 }
25952541
2596- #[ test]
2597- fn transport_environment_conflicts_with_legacy_environment ( ) {
2598- let options = ClientOptions :: new ( )
2599- . with_transport ( Transport :: Stdio {
2600- env : Some ( vec ! [ ( "NEW" . into( ) , "value" . into( ) ) ] ) ,
2601- } )
2602- . with_env ( [ ( "OLD" , "value" ) ] ) ;
2603-
2604- assert ! ( validate_transport_environment( & options) . is_err( ) ) ;
2605- }
2606-
2607- #[ test]
2608- fn legacy_environment_remains_supported_without_transport_environment ( ) {
2609- let options = ClientOptions :: new ( )
2610- . with_transport ( Transport :: Stdio { env : None } )
2611- . with_env ( [ ( "OLD" , "value" ) ] )
2612- . with_env_remove ( [ "REMOVED" ] ) ;
2613-
2614- assert ! ( validate_transport_environment( & options) . is_ok( ) ) ;
2615- }
2616-
2617- #[ test]
2618- fn transport_environment_is_applied_before_sdk_variables ( ) {
2619- let options = ClientOptions :: new ( )
2620- . with_transport ( Transport :: Stdio {
2621- env : Some ( vec ! [
2622- ( "CUSTOM" . into( ) , "value" . into( ) ) ,
2623- ( "COPILOT_SDK_AUTH_TOKEN" . into( ) , "old" . into( ) ) ,
2624- ] ) ,
2625- } )
2626- . with_github_token ( "new" ) ;
2627- let command = Client :: build_command ( Path :: new ( "/bin/echo" ) , & options, Path :: new ( "/tmp" ) ) ;
2628-
2629- assert_eq ! (
2630- env_value( & command, "CUSTOM" ) ,
2631- Some ( std:: ffi:: OsStr :: new( "value" ) )
2632- ) ;
2633- assert_eq ! (
2634- env_value( & command, "COPILOT_SDK_AUTH_TOKEN" ) ,
2635- Some ( std:: ffi:: OsStr :: new( "new" ) )
2636- ) ;
2637- }
2638-
26392542 #[ cfg( not( feature = "bundled-in-process" ) ) ]
26402543 #[ tokio:: test]
26412544 async fn inprocess_requires_cargo_feature ( ) {
@@ -2892,7 +2795,6 @@ mod tests {
28922795 let opts = ClientOptions :: new ( ) . with_transport ( Transport :: Tcp {
28932796 port : 0 ,
28942797 connection_token : Some ( "secret-token" . to_string ( ) ) ,
2895- env : None ,
28962798 } ) ;
28972799 let cmd = Client :: build_command ( Path :: new ( "/bin/echo" ) , & opts, Path :: new ( "/tmp" ) ) ;
28982800 assert_eq ! (
@@ -2911,7 +2813,6 @@ mod tests {
29112813 . with_transport ( Transport :: Tcp {
29122814 port : 0 ,
29132815 connection_token : Some ( String :: new ( ) ) ,
2914- env : None ,
29152816 } )
29162817 . with_program ( CliProgram :: Path ( PathBuf :: from ( "/bin/echo" ) ) ) ;
29172818 let err = Client :: start ( opts) . await . unwrap_err ( ) ;
0 commit comments