@@ -929,6 +929,7 @@ export function createPtyService({
929929 const exitListeners = new Set < PtyExitListener > ( ) ;
930930 const terminalChatSessions = new Map < string , string > ( ) ;
931931 const activeTerminalByChatSession = new Map < string , string > ( ) ;
932+ const activeAuxiliaryTerminalByChatSession = new Map < string , string > ( ) ;
932933 const missingResumeTargetBackfillFailures = new Map < string , { toolType : TerminalToolType | null ; checkedAtMs : number } > ( ) ;
933934 const claudeTitleCaptureKeys = new Set < string > ( ) ;
934935 const resumeRuntimeFlights = new Map < string , Promise < PtyCreateResult > > ( ) ;
@@ -2443,14 +2444,25 @@ export function createPtyService({
24432444 && isChatCliRoutingEntry ( entry )
24442445 && activeTerminalByChatSession . get ( entry . chatSessionId ) === entry . sessionId
24452446 ) {
2446- const replacement = liveChatCliEntriesFor ( entry . chatSessionId )
2447- . find ( ( candidate ) => candidate . sessionId !== entry . sessionId ) ?? null ;
2447+ const replacement = liveChatCliEntriesFor ( entry . chatSessionId ) [ 0 ] ?? null ;
24482448 if ( replacement ) {
24492449 activeTerminalByChatSession . set ( entry . chatSessionId , replacement . sessionId ) ;
24502450 } else {
24512451 activeTerminalByChatSession . delete ( entry . chatSessionId ) ;
24522452 }
24532453 }
2454+ if (
2455+ entry . chatSessionId
2456+ && isAuxiliaryRoutingEntry ( entry )
2457+ && activeAuxiliaryTerminalByChatSession . get ( entry . chatSessionId ) === entry . sessionId
2458+ ) {
2459+ const replacement = liveAuxiliaryEntriesFor ( entry . chatSessionId ) [ 0 ] ?? null ;
2460+ if ( replacement ) {
2461+ activeAuxiliaryTerminalByChatSession . set ( entry . chatSessionId , replacement . sessionId ) ;
2462+ } else {
2463+ activeAuxiliaryTerminalByChatSession . delete ( entry . chatSessionId ) ;
2464+ }
2465+ }
24542466 try {
24552467 onSessionRuntimeSignal ?.( {
24562468 laneId : entry . laneId ,
@@ -2694,6 +2706,9 @@ export function createPtyService({
26942706 const isChatCliRoutingEntry = ( entry : PtyEntry ) : boolean =>
26952707 isPersistedChatToolType ( entry . toolTypeHint ) ;
26962708
2709+ const isAuxiliaryRoutingEntry = ( entry : PtyEntry ) : boolean =>
2710+ ! isChatCliRoutingEntry ( entry ) ;
2711+
26972712 const liveChatCliEntriesFor = ( chatSessionId : string ) : PtyEntry [ ] =>
26982713 Array . from ( ptys . values ( ) )
26992714 . filter ( ( entry ) => (
@@ -2708,10 +2723,39 @@ export function createPtyService({
27082723 . filter ( ( entry ) => (
27092724 entry . chatSessionId === chatSessionId
27102725 && ! entry . disposed
2711- && ! isChatCliRoutingEntry ( entry )
2726+ && isAuxiliaryRoutingEntry ( entry )
27122727 ) )
27132728 . sort ( ( a , b ) => b . createdAt - a . createdAt ) ;
27142729
2730+ const activeEntryFromMap = (
2731+ map : Map < string , string > ,
2732+ chatSessionId : string ,
2733+ predicate : ( entry : PtyEntry ) => boolean ,
2734+ ) : PtyEntry | null => {
2735+ const sessionId = map . get ( chatSessionId ) ?? null ;
2736+ if ( ! sessionId ) return null ;
2737+ const live = liveEntryBySessionId ( sessionId ) ;
2738+ if ( live && live [ 1 ] . chatSessionId === chatSessionId && predicate ( live [ 1 ] ) ) return live [ 1 ] ;
2739+ map . delete ( chatSessionId ) ;
2740+ return null ;
2741+ } ;
2742+
2743+ const activeChatCliEntryFor = ( chatSessionId : string ) : PtyEntry | null => {
2744+ const active = activeEntryFromMap ( activeTerminalByChatSession , chatSessionId , isChatCliRoutingEntry ) ;
2745+ if ( active ) return active ;
2746+ const replacement = liveChatCliEntriesFor ( chatSessionId ) [ 0 ] ?? null ;
2747+ if ( replacement ) activeTerminalByChatSession . set ( chatSessionId , replacement . sessionId ) ;
2748+ return replacement ;
2749+ } ;
2750+
2751+ const activeAuxiliaryEntryFor = ( chatSessionId : string ) : PtyEntry | null => {
2752+ const active = activeEntryFromMap ( activeAuxiliaryTerminalByChatSession , chatSessionId , isAuxiliaryRoutingEntry ) ;
2753+ if ( active ) return active ;
2754+ const replacement = liveAuxiliaryEntriesFor ( chatSessionId ) [ 0 ] ?? null ;
2755+ if ( replacement ) activeAuxiliaryTerminalByChatSession . set ( chatSessionId , replacement . sessionId ) ;
2756+ return replacement ;
2757+ } ;
2758+
27152759 const promoteActiveChatCliTerminal = (
27162760 chatSessionId : string ,
27172761 sessionId : string ,
@@ -2721,6 +2765,27 @@ export function createPtyService({
27212765 activeTerminalByChatSession . set ( chatSessionId , sessionId ) ;
27222766 } ;
27232767
2768+ const promoteActiveAuxiliaryTerminal = (
2769+ chatSessionId : string ,
2770+ sessionId : string ,
2771+ toolType : TerminalToolType | null ,
2772+ ) : void => {
2773+ if ( isPersistedChatToolType ( toolType ) ) return ;
2774+ activeAuxiliaryTerminalByChatSession . set ( chatSessionId , sessionId ) ;
2775+ } ;
2776+
2777+ const promoteActiveChatTerminal = (
2778+ chatSessionId : string ,
2779+ sessionId : string ,
2780+ toolType : TerminalToolType | null ,
2781+ ) : void => {
2782+ if ( isPersistedChatToolType ( toolType ) ) {
2783+ promoteActiveChatCliTerminal ( chatSessionId , sessionId , toolType ) ;
2784+ } else {
2785+ promoteActiveAuxiliaryTerminal ( chatSessionId , sessionId , toolType ) ;
2786+ }
2787+ } ;
2788+
27242789 const codexReadyRegion = ( text : string ) : string => {
27252790 const lastPrompt = text . lastIndexOf ( "›" ) ;
27262791 if ( lastPrompt < 0 ) return text ;
@@ -2891,9 +2956,9 @@ export function createPtyService({
28912956 let active = false ;
28922957 if ( chatSessionId ) {
28932958 if ( isPersistedChatToolType ( summary . toolType ) ) {
2894- active = activeTerminalByChatSession . get ( chatSessionId ) === summary . id ;
2959+ active = activeChatCliEntryFor ( chatSessionId ) ?. sessionId === summary . id ;
28952960 } else {
2896- active = liveAuxiliaryEntriesFor ( chatSessionId ) [ 0 ] ?. sessionId === summary . id ;
2961+ active = activeAuxiliaryEntryFor ( chatSessionId ) ?. sessionId === summary . id ;
28972962 }
28982963 }
28992964 return {
@@ -2928,7 +2993,7 @@ export function createPtyService({
29282993 const chatSessionId = cleanOptionalId ( args . chatSessionId ) ;
29292994 if ( ! chatSessionId ) return null ;
29302995 // Auxiliary terminals (shell, App Control, etc.) — never route chat-CLI rows.
2931- return liveAuxiliaryEntriesFor ( chatSessionId ) [ 0 ] ?. sessionId ?? null ;
2996+ return activeAuxiliaryEntryFor ( chatSessionId ) ?. sessionId ?? null ;
29322997 } ;
29332998
29342999 const service = {
@@ -2990,7 +3055,7 @@ export function createPtyService({
29903055 if ( chatSessionId ) {
29913056 attachedEntry . chatSessionId = chatSessionId ;
29923057 terminalChatSessions . set ( existingSession . id , chatSessionId ) ;
2993- promoteActiveChatCliTerminal ( chatSessionId , existingSession . id , existingSession . toolType ) ;
3058+ promoteActiveChatTerminal ( chatSessionId , existingSession . id , existingSession . toolType ) ;
29943059 if ( existingSession . chatSessionId !== chatSessionId ) {
29953060 try { sessionService . setChatSessionId ( existingSession . id , chatSessionId ) ; } catch { }
29963061 }
@@ -3289,7 +3354,7 @@ export function createPtyService({
32893354 ptys . set ( ptyId , entry ) ;
32903355 if ( chatSessionId ) {
32913356 terminalChatSessions . set ( sessionId , chatSessionId ) ;
3292- promoteActiveChatCliTerminal ( chatSessionId , sessionId , toolTypeHint ) ;
3357+ promoteActiveChatTerminal ( chatSessionId , sessionId , toolTypeHint ) ;
32933358 if ( existingSession && existingSession . chatSessionId !== chatSessionId ) {
32943359 try { sessionService . setChatSessionId ( sessionId , chatSessionId ) ; } catch { }
32953360 }
@@ -3831,15 +3896,15 @@ export function createPtyService({
38313896 activeForChat ( args : ChatTerminalActiveForChatArgs ) : ChatTerminalSession | null {
38323897 const chatSessionId = cleanOptionalId ( args . chatSessionId ) ;
38333898 if ( ! chatSessionId ) return null ;
3834- const chatCli = liveChatCliEntriesFor ( chatSessionId ) [ 0 ] ?? null ;
3899+ const chatCli = activeChatCliEntryFor ( chatSessionId ) ;
38353900 if ( chatCli ) {
38363901 const session = sessionService . get ( chatCli . sessionId ) ;
38373902 if ( session ) {
38383903 promoteActiveChatCliTerminal ( chatSessionId , chatCli . sessionId , session . toolType ) ;
38393904 return terminalSessionFromSummary ( session ) ;
38403905 }
38413906 }
3842- const auxiliary = liveAuxiliaryEntriesFor ( chatSessionId ) [ 0 ] ?? null ;
3907+ const auxiliary = activeAuxiliaryEntryFor ( chatSessionId ) ;
38433908 if ( ! auxiliary ) return null ;
38443909 const session = sessionService . get ( auxiliary . sessionId ) ;
38453910 return session ? terminalSessionFromSummary ( session ) : null ;
@@ -3851,19 +3916,7 @@ export function createPtyService({
38513916
38523917 // Fast path: an existing live PTY is already bound. Skip the dedup map to
38533918 // keep the no-op cost low.
3854- const activeTerminalId = activeTerminalByChatSession . get ( chatSessionId ) ?? null ;
3855- if ( activeTerminalId ) {
3856- const liveActive = liveEntryBySessionId ( activeTerminalId ) ;
3857- if ( liveActive && isChatCliRoutingEntry ( liveActive [ 1 ] ) ) {
3858- return {
3859- terminalId : activeTerminalId ,
3860- ptyId : liveActive [ 0 ] ,
3861- pid : liveActive [ 1 ] . pty . pid ?? null ,
3862- relaunched : false ,
3863- } ;
3864- }
3865- }
3866- const liveChatCli = liveChatCliEntriesFor ( chatSessionId ) [ 0 ] ?? null ;
3919+ const liveChatCli = activeChatCliEntryFor ( chatSessionId ) ;
38673920 if ( liveChatCli ) {
38683921 const liveActive = liveEntryBySessionId ( liveChatCli . sessionId ) ;
38693922 if ( liveActive ) {
0 commit comments