@@ -39,7 +39,7 @@ use super::CommandContext;
3939/// commands (e.g. `code agent ps`) can discover a running agent host.
4040#[ derive( Debug , Clone , Serialize , Deserialize ) ]
4141pub struct AgentHostLockData {
42- /// WebSocket address the agent host is listening on (e.g. `ws://127.0.0.1:4567`).
42+ /// WebSocket address the agent host is listening on (e.g. `ws://127.0.0.1:4567/ `).
4343 pub address : String ,
4444 /// PID of the CLI process running the agent host.
4545 pub pid : u32 ,
@@ -125,10 +125,7 @@ pub async fn agent_host(ctx: CommandContext, mut args: AgentHostArgs) -> Result<
125125 . local_addr ( )
126126 . map_err ( CodeError :: CouldNotListenOnInterface ) ?;
127127
128- let mut url = format ! ( "ws://{bound_addr}" ) ;
129- if let Some ( ct) = & args. connection_token {
130- url. push_str ( & format ! ( "?tkn={ct}" ) ) ;
131- }
128+ let local_agent_host_url = format ! ( "ws://{bound_addr}/" ) ;
132129
133130 let product = constants:: QUALITYLESS_PRODUCT_NAME ;
134131 let token_suffix = args
@@ -199,12 +196,12 @@ pub async fn agent_host(ctx: CommandContext, mut args: AgentHostArgs) -> Result<
199196 // Write lockfile so `code agent ps` can discover this instance.
200197 let lockfile_path = ctx. paths . agent_host_lockfile ( ) ;
201198 let lock_data = AgentHostLockData {
202- address : format ! ( "ws://{bound_addr}/" ) ,
199+ address : local_agent_host_url ,
203200 pid : std:: process:: id ( ) ,
204201 connection_token : args. connection_token . clone ( ) ,
205202 tunnel_name : tunnel_name. clone ( ) ,
206203 } ;
207- if let Err ( e) = fs :: write ( & lockfile_path, serde_json :: to_string ( & lock_data) . unwrap ( ) ) {
204+ if let Err ( e) = write_agent_host_lockfile ( & lockfile_path, & lock_data) {
208205 warning ! ( ctx. log, "Failed to write agent host lockfile: {}" , e) ;
209206 }
210207
@@ -290,29 +287,45 @@ fn mint_connection_token(path: &Path, prefer_token: Option<String>) -> std::io::
290287 #[ cfg( not( windows) ) ]
291288 use std:: os:: unix:: fs:: OpenOptionsExt ;
292289
293- let mut f = fs:: OpenOptions :: new ( ) ;
294- f . create ( true ) ;
295- f . write ( true ) ;
296- f . read ( true ) ;
290+ let mut file_options = fs:: OpenOptions :: new ( ) ;
291+ file_options . create ( true ) ;
292+ file_options . write ( true ) ;
293+ file_options . read ( true ) ;
297294 #[ cfg( not( windows) ) ]
298- f . mode ( 0o600 ) ;
299- let mut f = f . open ( path) ?;
295+ file_options . mode ( 0o600 ) ;
296+ let mut file = file_options . open ( path) ?;
300297
301298 if prefer_token. is_none ( ) {
302- let mut t = String :: new ( ) ;
303- f . read_to_string ( & mut t ) ?;
304- let t = t . trim ( ) ;
305- if !t . is_empty ( ) {
306- return Ok ( t . to_string ( ) ) ;
299+ let mut token = String :: new ( ) ;
300+ file . read_to_string ( & mut token ) ?;
301+ let token = token . trim ( ) ;
302+ if !token . is_empty ( ) {
303+ return Ok ( token . to_string ( ) ) ;
307304 }
308305 }
309306
310- f . set_len ( 0 ) ?;
307+ file . set_len ( 0 ) ?;
311308 let prefer_token = prefer_token. unwrap_or_else ( || uuid:: Uuid :: new_v4 ( ) . to_string ( ) ) ;
312- f . write_all ( prefer_token. as_bytes ( ) ) ?;
309+ file . write_all ( prefer_token. as_bytes ( ) ) ?;
313310 Ok ( prefer_token)
314311}
315312
313+ fn write_agent_host_lockfile ( path : & Path , lock_data : & AgentHostLockData ) -> std:: io:: Result < ( ) > {
314+ #[ cfg( not( windows) ) ]
315+ use std:: os:: unix:: fs:: { OpenOptionsExt , PermissionsExt } ;
316+
317+ let mut file_options = fs:: OpenOptions :: new ( ) ;
318+ file_options. create ( true ) ;
319+ file_options. write ( true ) ;
320+ file_options. truncate ( true ) ;
321+ #[ cfg( not( windows) ) ]
322+ file_options. mode ( 0o600 ) ;
323+ let mut file = file_options. open ( path) ?;
324+ #[ cfg( not( windows) ) ]
325+ file. set_permissions ( fs:: Permissions :: from_mode ( 0o600 ) ) ?;
326+ file. write_all ( serde_json:: to_string ( lock_data) . unwrap ( ) . as_bytes ( ) )
327+ }
328+
316329#[ cfg( test) ]
317330mod tests {
318331 use super :: * ;
0 commit comments