@@ -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" ;
@@ -79,6 +79,8 @@ export interface SessionState {
7979 modelContextWindow : number | null ;
8080 rateLimits : RateLimitsMap | null ;
8181 account : Account | null ;
82+ authConfigured : boolean ;
83+ authProvider : string | null ;
8284 cwd : string ;
8385 additionalDirectories : string [ ] ;
8486 fastModeEnabled : boolean ;
@@ -87,6 +89,11 @@ export interface SessionState {
8789 terminalOutputMode : TerminalOutputMode ;
8890}
8991
92+ interface ActiveAuthState {
93+ account : Account | null ;
94+ authConfigured : boolean ;
95+ }
96+
9097interface PendingMcpStartupSession {
9198 requestedServers : Set < string > ;
9299 afterVersion : number ;
@@ -156,7 +163,8 @@ export class CodexAcpServer {
156163 this . availableCommands = new CodexCommands (
157164 connection ,
158165 codexAcpClient ,
159- ( operation ) => this . runWithProcessCheck ( operation )
166+ ( operation ) => this . runWithProcessCheck ( operation ) ,
167+ ( ) => this . refreshSessionsAuthState ( null )
160168 ) ;
161169 }
162170
@@ -247,6 +255,7 @@ export class CodexAcpServer {
247255 async handleError ( e : Error ) {
248256 if ( e . message . includes ( "log out" ) || e . message . includes ( "cloud requirements" ) ) {
249257 await this . runWithProcessCheck ( ( ) => this . codexAcpClient . logout ( ) ) ;
258+ await this . refreshSessionsAuthState ( null ) ;
250259 throw RequestError . internalError ( `${ ( e . message ) } \n\nYou have been logged out. Please try again.` ) ;
251260 }
252261 }
@@ -346,9 +355,10 @@ export class CodexAcpServer {
346355 }
347356
348357 const { sessionId, currentModelId, models} = sessionMetadata ;
349- let account : Account | null ;
358+ const authProvider = sessionMetadata . modelProvider ?? this . codexAcpClient . getModelProvider ( ) ;
359+ let authState : ActiveAuthState ;
350360 try {
351- account = await this . getActiveAccount ( ) ;
361+ authState = await this . getAuthStateForProvider ( authProvider ) ;
352362 } catch ( err ) {
353363 if ( resumeSubscribed && requestedSessionGeneration !== null ) {
354364 await this . cleanupStaleSessionOpen ( sessionId , requestedSessionGeneration ) ;
@@ -375,7 +385,9 @@ export class CodexAcpServer {
375385 totalTokenUsage : null ,
376386 modelContextWindow : null ,
377387 rateLimits : null ,
378- account : account ,
388+ account : authState . account ,
389+ authConfigured : authState . authConfigured ,
390+ authProvider : authProvider ,
379391 cwd : request . cwd ,
380392 additionalDirectories : sessionMetadata . additionalDirectories ,
381393 fastModeEnabled : sessionMetadata . currentServiceTier === "fast" ,
@@ -401,12 +413,36 @@ export class CodexAcpServer {
401413 return [ sessionId , sessionModelState , sessionModeState ] ;
402414 }
403415
404- private async getActiveAccount ( ) {
405- if ( this . codexAcpClient . getModelProvider ( ) ) {
406- return null
416+ private async getAuthStateForProvider ( authProvider : string | null ) : Promise < ActiveAuthState > {
417+ if ( ! this . authProviderUsesOpenAiAccount ( authProvider ) ) {
418+ return {
419+ account : null ,
420+ authConfigured : true ,
421+ } ;
407422 }
408423 const accountResponse = await this . runWithProcessCheck ( ( ) => this . codexAcpClient . getAccount ( ) ) ;
409- return accountResponse . account ;
424+ return {
425+ account : accountResponse . account ,
426+ authConfigured : accountResponse . account !== null || ! accountResponse . requiresOpenaiAuth ,
427+ } ;
428+ }
429+
430+ private authProviderUsesOpenAiAccount ( authProvider : string | null ) : boolean {
431+ return authProvider === null || authProvider === "openai" ;
432+ }
433+
434+ private authProvidersMatch ( a : string | null , b : string | null ) : boolean {
435+ if ( this . authProviderUsesOpenAiAccount ( a ) && this . authProviderUsesOpenAiAccount ( b ) ) {
436+ return true ;
437+ }
438+ return a === b ;
439+ }
440+
441+ private getAuthProviderForAuthenticateRequest ( request : acp . AuthenticateRequest ) : string | null {
442+ if ( isCodexAuthRequest ( request ) && request . methodId === "gateway" ) {
443+ return "custom-gateway" ;
444+ }
445+ return null ;
410446 }
411447
412448 async loadSession ( params : acp . LoadSessionRequest ) : Promise < LegacyLoadSessionResponse > {
@@ -565,16 +601,32 @@ export class CodexAcpServer {
565601 logger . log ( "Authenticate request failed" ) ;
566602 throw RequestError . invalidParams ( ) ;
567603 }
604+ await this . refreshSessionsAuthState ( this . getAuthProviderForAuthenticateRequest ( _params ) ) ;
568605 logger . log ( "Authenticate request completed" ) ;
569606 return { } ;
570607 }
571608
572609 async logout ( _params : acp . LogoutRequest ) : Promise < void > {
573610 logger . log ( "Logout request received" ) ;
574611 await this . runWithProcessCheck ( ( ) => this . codexAcpClient . logout ( ) ) ;
612+ await this . refreshSessionsAuthState ( null ) ;
575613 logger . log ( "Logout request completed" ) ;
576614 }
577615
616+ private async refreshSessionsAuthState ( authProvider : string | null ) : Promise < void > {
617+ if ( this . sessions . size === 0 ) return ;
618+
619+ const sessionsToRefresh = [ ...this . sessions . values ( ) ]
620+ . filter ( sessionState => this . authProvidersMatch ( sessionState . authProvider , authProvider ) ) ;
621+ if ( sessionsToRefresh . length === 0 ) return ;
622+
623+ const authState = await this . getAuthStateForProvider ( authProvider ) ;
624+ for ( const sessionState of sessionsToRefresh ) {
625+ sessionState . account = authState . account ;
626+ sessionState . authConfigured = authState . authConfigured ;
627+ }
628+ }
629+
578630 async setSessionMode (
579631 _params : acp . SetSessionModeRequest ,
580632 ) : Promise < acp . SetSessionModeResponse > {
@@ -798,9 +850,10 @@ export class CodexAcpServer {
798850 }
799851
800852 const { sessionId, currentModelId, models, thread} = sessionMetadata ;
801- let account : Account | null ;
853+ const authProvider = sessionMetadata . modelProvider ?? this . codexAcpClient . getModelProvider ( ) ;
854+ let authState : ActiveAuthState ;
802855 try {
803- account = await this . getActiveAccount ( ) ;
856+ authState = await this . getAuthStateForProvider ( authProvider ) ;
804857 } catch ( err ) {
805858 if ( subscribed ) {
806859 await this . cleanupStaleSessionOpen ( request . sessionId , requestedSessionGeneration ) ;
@@ -826,7 +879,9 @@ export class CodexAcpServer {
826879 totalTokenUsage : null ,
827880 modelContextWindow : null ,
828881 rateLimits : null ,
829- account : account ,
882+ account : authState . account ,
883+ authConfigured : authState . authConfigured ,
884+ authProvider : authProvider ,
830885 cwd : request . cwd ,
831886 additionalDirectories : sessionMetadata . additionalDirectories ,
832887 fastModeEnabled : sessionMetadata . currentServiceTier === "fast" ,
0 commit comments