@@ -179,6 +179,7 @@ async fn run_print(invocation: Invocation) -> Result<i32> {
179179 args : passthrough_args. clone ( ) ,
180180 session_id : current_session_id. clone ( ) ,
181181 invocation : & invocation,
182+ allow_session_strip_on_next_prepare : false ,
182183 } ;
183184 run_stream_json (
184185 & mut process,
@@ -392,13 +393,15 @@ struct StreamSpawnContext<'a> {
392393 args : Vec < String > ,
393394 session_id : Option < String > ,
394395 invocation : & ' a Invocation ,
396+ allow_session_strip_on_next_prepare : bool ,
395397}
396398
397399async fn ensure_sdk_mcp_runtime (
398400 process : & mut PtyProcess ,
401+ tail : & mut TailCursor ,
399402 input : & mut mpsc:: Receiver < Value > ,
400403 sdk_state : & mut SdkStreamState ,
401- spawn : & StreamSpawnContext < ' _ > ,
404+ spawn : & mut StreamSpawnContext < ' _ > ,
402405) -> Result < bool > {
403406 if sdk_state. mcp_runtime . is_some ( ) {
404407 return Ok ( false ) ;
@@ -429,7 +432,7 @@ async fn ensure_sdk_mcp_runtime(
429432 & spawn. session_id ,
430433 spawn. invocation ,
431434 ) ?;
432- prepare_tty_for_prompt_with_mcp_retrying_session_lock (
435+ match prepare_tty_for_prompt_with_mcp_retrying_session_lock (
433436 process,
434437 input,
435438 & runtime,
@@ -438,7 +441,49 @@ async fn ensure_sdk_mcp_runtime(
438441 & rewritten_args,
439442 & spawn. session_id ,
440443 )
441- . await ?;
444+ . await
445+ {
446+ Ok ( ( ) ) => {
447+ spawn. allow_session_strip_on_next_prepare = false ;
448+ }
449+ Err ( error)
450+ if is_session_lock_startup_error ( & error)
451+ && spawn. allow_session_strip_on_next_prepare =>
452+ {
453+ let stripped_args = strip_session_resume_args ( & spawn. args ) ;
454+ if stripped_args == spawn. args {
455+ return Err ( error) ;
456+ }
457+ let rewritten_stripped_args = args_with_mcp_runtime ( & stripped_args, & runtime) ?;
458+ logging:: event (
459+ "tty_restart reason=control_update_session_lock action=strip_session_args" ,
460+ ) ;
461+ process. terminate ( PTY_TERMINATE_TIMEOUT ) ;
462+ * process = spawn_tty_process (
463+ spawn. claude ,
464+ spawn. cwd ,
465+ spawn. env ,
466+ & rewritten_stripped_args,
467+ & None ,
468+ spawn. invocation ,
469+ ) ?;
470+ prepare_tty_for_prompt_with_mcp_retrying_session_lock (
471+ process,
472+ input,
473+ & runtime,
474+ sdk_state,
475+ spawn,
476+ & rewritten_stripped_args,
477+ & None ,
478+ )
479+ . await ?;
480+ spawn. args = stripped_args;
481+ spawn. session_id = None ;
482+ spawn. allow_session_strip_on_next_prepare = false ;
483+ tail. reset_for_new_session ( ) ;
484+ }
485+ Err ( error) => return Err ( error) ,
486+ }
442487 sdk_state. mcp_runtime = Some ( runtime) ;
443488 Ok ( true )
444489}
@@ -483,7 +528,7 @@ async fn run_stream_json(
483528 Some ( "control_response" ) => { }
484529 Some ( "control_cancel_request" ) => { }
485530 Some ( "user" ) => {
486- if ensure_sdk_mcp_runtime ( process, & mut input, & mut sdk_state, spawn) . await ? {
531+ if ensure_sdk_mcp_runtime ( process, tail , & mut input, & mut sdk_state, spawn) . await ? {
487532 tty_prepared = true ;
488533 }
489534 if !tty_prepared {
@@ -521,7 +566,7 @@ async fn prepare_stream_tty_for_prompt_with_sdk_state(
521566 tail : & mut TailCursor ,
522567 input : & mut mpsc:: Receiver < Value > ,
523568 sdk_state : & mut SdkStreamState ,
524- spawn : & StreamSpawnContext < ' _ > ,
569+ spawn : & mut StreamSpawnContext < ' _ > ,
525570) -> Result < ( ) > {
526571 let Some ( runtime) = sdk_state. mcp_runtime . take ( ) else {
527572 return prepare_stream_tty_for_prompt ( process, tail, spawn) . await ;
@@ -537,7 +582,7 @@ async fn prepare_stream_tty_for_prompt_with_sdk_state(
537582async fn prepare_stream_tty_for_prompt (
538583 process : & mut PtyProcess ,
539584 tail : & mut TailCursor ,
540- spawn : & StreamSpawnContext < ' _ > ,
585+ spawn : & mut StreamSpawnContext < ' _ > ,
541586) -> Result < ( ) > {
542587 match prepare_tty_for_prompt_retrying_session_lock (
543588 process,
@@ -550,7 +595,46 @@ async fn prepare_stream_tty_for_prompt(
550595 )
551596 . await
552597 {
553- Ok ( ( ) ) => Ok ( ( ) ) ,
598+ Ok ( ( ) ) => {
599+ spawn. allow_session_strip_on_next_prepare = false ;
600+ Ok ( ( ) )
601+ }
602+ Err ( error)
603+ if is_session_lock_startup_error ( & error)
604+ && spawn. allow_session_strip_on_next_prepare =>
605+ {
606+ let stripped_args = strip_session_resume_args ( & spawn. args ) ;
607+ if stripped_args == spawn. args {
608+ return Err ( error) ;
609+ }
610+ logging:: event (
611+ "tty_restart reason=control_update_session_lock action=strip_session_args" ,
612+ ) ;
613+ process. terminate ( PTY_TERMINATE_TIMEOUT ) ;
614+ * process = spawn_tty_process (
615+ spawn. claude ,
616+ spawn. cwd ,
617+ spawn. env ,
618+ & stripped_args,
619+ & None ,
620+ spawn. invocation ,
621+ ) ?;
622+ prepare_tty_for_prompt_retrying_session_lock (
623+ process,
624+ spawn. claude ,
625+ spawn. cwd ,
626+ spawn. env ,
627+ & stripped_args,
628+ & None ,
629+ spawn. invocation ,
630+ )
631+ . await ?;
632+ spawn. args = stripped_args;
633+ spawn. session_id = None ;
634+ spawn. allow_session_strip_on_next_prepare = false ;
635+ tail. reset_for_new_session ( ) ;
636+ Ok ( ( ) )
637+ }
554638 Err ( error) if is_bad_resume_startup_error ( & error) => {
555639 let stripped_args = strip_session_resume_args ( & spawn. args ) ;
556640 if stripped_args == spawn. args {
@@ -576,6 +660,9 @@ async fn prepare_stream_tty_for_prompt(
576660 spawn. invocation ,
577661 )
578662 . await ?;
663+ spawn. args = stripped_args;
664+ spawn. session_id = None ;
665+ spawn. allow_session_strip_on_next_prepare = false ;
579666 tail. reset_for_new_session ( ) ;
580667 Ok ( ( ) )
581668 }
@@ -589,7 +676,7 @@ async fn prepare_stream_tty_for_prompt_with_mcp_runtime(
589676 input : & mut mpsc:: Receiver < Value > ,
590677 runtime : & SdkMcpRuntime ,
591678 sdk_state : & mut SdkStreamState ,
592- spawn : & StreamSpawnContext < ' _ > ,
679+ spawn : & mut StreamSpawnContext < ' _ > ,
593680) -> Result < ( ) > {
594681 let rewritten_spawn_args = args_with_mcp_runtime ( & spawn. args , runtime) ?;
595682 match prepare_tty_for_prompt_with_mcp_retrying_session_lock (
@@ -603,7 +690,47 @@ async fn prepare_stream_tty_for_prompt_with_mcp_runtime(
603690 )
604691 . await
605692 {
606- Ok ( ( ) ) => Ok ( ( ) ) ,
693+ Ok ( ( ) ) => {
694+ spawn. allow_session_strip_on_next_prepare = false ;
695+ Ok ( ( ) )
696+ }
697+ Err ( error)
698+ if is_session_lock_startup_error ( & error)
699+ && spawn. allow_session_strip_on_next_prepare =>
700+ {
701+ let stripped_args = strip_session_resume_args ( & spawn. args ) ;
702+ if stripped_args == spawn. args {
703+ return Err ( error) ;
704+ }
705+ let rewritten_args = args_with_mcp_runtime ( & stripped_args, runtime) ?;
706+ logging:: event (
707+ "tty_restart reason=control_update_session_lock action=strip_session_args" ,
708+ ) ;
709+ process. terminate ( PTY_TERMINATE_TIMEOUT ) ;
710+ * process = spawn_tty_process (
711+ spawn. claude ,
712+ spawn. cwd ,
713+ spawn. env ,
714+ & rewritten_args,
715+ & None ,
716+ spawn. invocation ,
717+ ) ?;
718+ prepare_tty_for_prompt_with_mcp_retrying_session_lock (
719+ process,
720+ input,
721+ runtime,
722+ sdk_state,
723+ spawn,
724+ & rewritten_args,
725+ & None ,
726+ )
727+ . await ?;
728+ spawn. args = stripped_args;
729+ spawn. session_id = None ;
730+ spawn. allow_session_strip_on_next_prepare = false ;
731+ tail. reset_for_new_session ( ) ;
732+ Ok ( ( ) )
733+ }
607734 Err ( error) if is_bad_resume_startup_error ( & error) => {
608735 let stripped_args = strip_session_resume_args ( & spawn. args ) ;
609736 if stripped_args == spawn. args {
@@ -630,6 +757,9 @@ async fn prepare_stream_tty_for_prompt_with_mcp_runtime(
630757 & None ,
631758 )
632759 . await ?;
760+ spawn. args = stripped_args;
761+ spawn. session_id = None ;
762+ spawn. allow_session_strip_on_next_prepare = false ;
633763 tail. reset_for_new_session ( ) ;
634764 Ok ( ( ) )
635765 }
0 commit comments