@@ -3,7 +3,7 @@ import {RequestError, type SessionId, type SessionModeState} from "@agentclientp
33import { CodexEventHandler } from "./CodexEventHandler" ;
44import { CodexApprovalHandler } from "./CodexApprovalHandler" ;
55import { CodexElicitationHandler } from "./CodexElicitationHandler" ;
6- import { type CodexAuthRequest , getCodexAuthMethods } from "./CodexAuthMethod" ;
6+ import { type CodexAuthRequest , getCodexAuthMethods , isCodexAuthRequest } from "./CodexAuthMethod" ;
77import { CodexAcpClient , type SessionMetadata , type SessionMetadataWithThread } from "./CodexAcpClient" ;
88import type { McpStartupResult } from "./CodexAppServerClient" ;
99import { ACPSessionConnection , type AcpClientConnection , type UpdateSessionEvent } from "./ACPSessionConnection" ;
@@ -86,6 +86,8 @@ export interface SessionState {
8686 modelContextWindow : number | null ;
8787 rateLimits : RateLimitsMap | null ;
8888 account : Account | null ;
89+ authConfigured : boolean ;
90+ authProvider : string | null ;
8991 cwd : string ;
9092 additionalDirectories : string [ ] ;
9193 fastModeEnabled : boolean ;
@@ -95,6 +97,11 @@ export interface SessionState {
9597 currentGoal ?: ThreadGoalSnapshot | null ;
9698}
9799
100+ interface ActiveAuthState {
101+ account : Account | null ;
102+ authConfigured : boolean ;
103+ }
104+
98105interface PendingMcpStartupSession {
99106 requestedServers : Set < string > ;
100107 afterVersion : number ;
@@ -164,7 +171,8 @@ export class CodexAcpServer {
164171 this . availableCommands = new CodexCommands (
165172 connection ,
166173 codexAcpClient ,
167- ( operation ) => this . runWithProcessCheck ( operation )
174+ ( operation ) => this . runWithProcessCheck ( operation ) ,
175+ ( ) => this . refreshSessionsAuthState ( null )
168176 ) ;
169177 }
170178
@@ -255,6 +263,7 @@ export class CodexAcpServer {
255263 async handleError ( e : Error ) {
256264 if ( e . message . includes ( "log out" ) || e . message . includes ( "cloud requirements" ) ) {
257265 await this . runWithProcessCheck ( ( ) => this . codexAcpClient . logout ( ) ) ;
266+ await this . refreshSessionsAuthState ( null ) ;
258267 throw RequestError . internalError ( `${ ( e . message ) } \n\nYou have been logged out. Please try again.` ) ;
259268 }
260269 }
@@ -354,9 +363,10 @@ export class CodexAcpServer {
354363 }
355364
356365 const { sessionId, currentModelId, models} = sessionMetadata ;
357- let account : Account | null ;
366+ const authProvider = sessionMetadata . modelProvider ?? this . codexAcpClient . getModelProvider ( ) ;
367+ let authState : ActiveAuthState ;
358368 try {
359- account = await this . getActiveAccount ( ) ;
369+ authState = await this . getAuthStateForProvider ( authProvider ) ;
360370 } catch ( err ) {
361371 if ( resumeSubscribed && requestedSessionGeneration !== null ) {
362372 await this . cleanupStaleSessionOpen ( sessionId , requestedSessionGeneration ) ;
@@ -383,7 +393,9 @@ export class CodexAcpServer {
383393 totalTokenUsage : null ,
384394 modelContextWindow : null ,
385395 rateLimits : null ,
386- account : account ,
396+ account : authState . account ,
397+ authConfigured : authState . authConfigured ,
398+ authProvider : authProvider ,
387399 cwd : request . cwd ,
388400 additionalDirectories : sessionMetadata . additionalDirectories ,
389401 fastModeEnabled : sessionMetadata . currentServiceTier === "fast" ,
@@ -409,12 +421,36 @@ export class CodexAcpServer {
409421 return [ sessionId , sessionModelState , sessionModeState ] ;
410422 }
411423
412- private async getActiveAccount ( ) {
413- if ( this . codexAcpClient . getModelProvider ( ) ) {
414- return null
424+ private async getAuthStateForProvider ( authProvider : string | null ) : Promise < ActiveAuthState > {
425+ if ( ! this . authProviderUsesOpenAiAccount ( authProvider ) ) {
426+ return {
427+ account : null ,
428+ authConfigured : true ,
429+ } ;
415430 }
416431 const accountResponse = await this . runWithProcessCheck ( ( ) => this . codexAcpClient . getAccount ( ) ) ;
417- return accountResponse . account ;
432+ return {
433+ account : accountResponse . account ,
434+ authConfigured : accountResponse . account !== null || ! accountResponse . requiresOpenaiAuth ,
435+ } ;
436+ }
437+
438+ private authProviderUsesOpenAiAccount ( authProvider : string | null ) : boolean {
439+ return authProvider === null || authProvider === "openai" ;
440+ }
441+
442+ private authProvidersMatch ( a : string | null , b : string | null ) : boolean {
443+ if ( this . authProviderUsesOpenAiAccount ( a ) && this . authProviderUsesOpenAiAccount ( b ) ) {
444+ return true ;
445+ }
446+ return a === b ;
447+ }
448+
449+ private getAuthProviderForAuthenticateRequest ( request : acp . AuthenticateRequest ) : string | null {
450+ if ( isCodexAuthRequest ( request ) && request . methodId === "gateway" ) {
451+ return "custom-gateway" ;
452+ }
453+ return null ;
418454 }
419455
420456 async loadSession ( params : acp . LoadSessionRequest ) : Promise < LegacyLoadSessionResponse > {
@@ -573,16 +609,32 @@ export class CodexAcpServer {
573609 logger . log ( "Authenticate request failed" ) ;
574610 throw RequestError . invalidParams ( ) ;
575611 }
612+ await this . refreshSessionsAuthState ( this . getAuthProviderForAuthenticateRequest ( _params ) ) ;
576613 logger . log ( "Authenticate request completed" ) ;
577614 return { } ;
578615 }
579616
580617 async logout ( _params : acp . LogoutRequest ) : Promise < void > {
581618 logger . log ( "Logout request received" ) ;
582619 await this . runWithProcessCheck ( ( ) => this . codexAcpClient . logout ( ) ) ;
620+ await this . refreshSessionsAuthState ( null ) ;
583621 logger . log ( "Logout request completed" ) ;
584622 }
585623
624+ private async refreshSessionsAuthState ( authProvider : string | null ) : Promise < void > {
625+ if ( this . sessions . size === 0 ) return ;
626+
627+ const sessionsToRefresh = [ ...this . sessions . values ( ) ]
628+ . filter ( sessionState => this . authProvidersMatch ( sessionState . authProvider , authProvider ) ) ;
629+ if ( sessionsToRefresh . length === 0 ) return ;
630+
631+ const authState = await this . getAuthStateForProvider ( authProvider ) ;
632+ for ( const sessionState of sessionsToRefresh ) {
633+ sessionState . account = authState . account ;
634+ sessionState . authConfigured = authState . authConfigured ;
635+ }
636+ }
637+
586638 async setSessionMode (
587639 _params : acp . SetSessionModeRequest ,
588640 ) : Promise < acp . SetSessionModeResponse > {
@@ -806,9 +858,10 @@ export class CodexAcpServer {
806858 }
807859
808860 const { sessionId, currentModelId, models, thread} = sessionMetadata ;
809- let account : Account | null ;
861+ const authProvider = sessionMetadata . modelProvider ?? this . codexAcpClient . getModelProvider ( ) ;
862+ let authState : ActiveAuthState ;
810863 try {
811- account = await this . getActiveAccount ( ) ;
864+ authState = await this . getAuthStateForProvider ( authProvider ) ;
812865 } catch ( err ) {
813866 if ( subscribed ) {
814867 await this . cleanupStaleSessionOpen ( request . sessionId , requestedSessionGeneration ) ;
@@ -834,7 +887,9 @@ export class CodexAcpServer {
834887 totalTokenUsage : null ,
835888 modelContextWindow : null ,
836889 rateLimits : null ,
837- account : account ,
890+ account : authState . account ,
891+ authConfigured : authState . authConfigured ,
892+ authProvider : authProvider ,
838893 cwd : request . cwd ,
839894 additionalDirectories : sessionMetadata . additionalDirectories ,
840895 fastModeEnabled : sessionMetadata . currentServiceTier === "fast" ,
0 commit comments