@@ -74,6 +74,7 @@ type SelectedConnectAuth = {
7474 authBootstrapToken ?: string ;
7575 authDeviceToken ?: string ;
7676 authPassword ?: string ;
77+ authApprovalRuntimeToken ?: string ;
7778 signatureToken ?: string ;
7879 resolvedDeviceToken ?: string ;
7980 storedToken ?: string ;
@@ -130,6 +131,7 @@ export type GatewayClientOptions = {
130131 bootstrapToken ?: string ;
131132 deviceToken ?: string ;
132133 password ?: string ;
134+ approvalRuntimeToken ?: string ;
133135 instanceId ?: string ;
134136 clientName ?: GatewayClientName ;
135137 clientDisplayName ?: string ;
@@ -221,6 +223,8 @@ export class GatewayClient {
221223 private reconnectTimer : NodeJS . Timeout | null = null ;
222224 private pendingDeviceTokenRetry = false ;
223225 private deviceTokenRetryBudgetUsed = false ;
226+ private approvalRuntimeTokenCompatibilityDisabled = false ;
227+ private approvalRuntimeTokenRetryBudgetUsed = false ;
224228 private pendingStartupReconnectDelayMs : number | null = null ;
225229 private pendingConnectErrorDetailCode : string | null = null ;
226230 private pendingConnectErrorDetails : unknown = null ;
@@ -506,6 +510,7 @@ export class GatewayClient {
506510 authBootstrapToken,
507511 authDeviceToken,
508512 authPassword,
513+ authApprovalRuntimeToken,
509514 signatureToken,
510515 resolvedDeviceToken,
511516 storedToken,
@@ -516,12 +521,17 @@ export class GatewayClient {
516521 this . pendingDeviceTokenRetry = false ;
517522 }
518523 const auth =
519- authToken || authBootstrapToken || authPassword || resolvedDeviceToken
524+ authToken ||
525+ authBootstrapToken ||
526+ authPassword ||
527+ resolvedDeviceToken ||
528+ authApprovalRuntimeToken
520529 ? {
521530 token : authToken ,
522531 bootstrapToken : authBootstrapToken ,
523532 deviceToken : authDeviceToken ?? resolvedDeviceToken ,
524533 password : authPassword ,
534+ approvalRuntimeToken : authApprovalRuntimeToken ,
525535 }
526536 : undefined ;
527537 const signedAtMs = Date . now ( ) ;
@@ -646,6 +656,19 @@ export class GatewayClient {
646656 this . ws ?. close ( 1013 , "gateway starting" ) ;
647657 return ;
648658 }
659+ if (
660+ this . shouldRetryWithoutApprovalRuntimeToken ( {
661+ error : err ,
662+ authApprovalRuntimeToken,
663+ } )
664+ ) {
665+ this . approvalRuntimeTokenCompatibilityDisabled = true ;
666+ this . approvalRuntimeTokenRetryBudgetUsed = true ;
667+ this . backoffMs = Math . min ( this . backoffMs , 250 ) ;
668+ logDebug ( "gateway rejected approval runtime auth field; retrying without it" ) ;
669+ this . ws ?. close ( 1008 , "connect retry" ) ;
670+ return ;
671+ }
649672 this . opts . onConnectError ?.( err instanceof Error ? err : new Error ( String ( err ) ) ) ;
650673 const msg = `gateway connect failed: ${ String ( err ) } ` ;
651674 if ( this . opts . mode === GATEWAY_CLIENT_MODES . PROBE || isGatewayClientStoppedError ( err ) ) {
@@ -763,6 +786,26 @@ export class GatewayClient {
763786 ) ;
764787 }
765788
789+ private shouldRetryWithoutApprovalRuntimeToken ( params : {
790+ error : unknown ;
791+ authApprovalRuntimeToken ?: string ;
792+ } ) : boolean {
793+ if ( this . approvalRuntimeTokenRetryBudgetUsed ) {
794+ return false ;
795+ }
796+ if ( ! params . authApprovalRuntimeToken ) {
797+ return false ;
798+ }
799+ if ( ! ( params . error instanceof GatewayClientRequestError ) ) {
800+ return false ;
801+ }
802+ if ( params . error . gatewayCode !== "INVALID_REQUEST" ) {
803+ return false ;
804+ }
805+ const message = normalizeLowercaseStringOrEmpty ( params . error . message ) ;
806+ return message . includes ( "invalid connect params" ) && message . includes ( "approvalruntimetoken" ) ;
807+ }
808+
766809 private isTrustedDeviceRetryEndpoint ( ) : boolean {
767810 const rawUrl = this . opts . url ?? "ws://127.0.0.1:18789" ;
768811 try {
@@ -787,6 +830,9 @@ export class GatewayClient {
787830 const explicitBootstrapToken = normalizeOptionalString ( this . opts . bootstrapToken ) ;
788831 const explicitDeviceToken = normalizeOptionalString ( this . opts . deviceToken ) ;
789832 const authPassword = normalizeOptionalString ( this . opts . password ) ;
833+ const authApprovalRuntimeToken = this . approvalRuntimeTokenCompatibilityDisabled
834+ ? undefined
835+ : normalizeOptionalString ( this . opts . approvalRuntimeToken ) ;
790836 const storedAuth = this . loadStoredDeviceAuth ( role ) ;
791837 const storedToken = storedAuth ?. token ?? null ;
792838 const storedScopes = storedAuth ?. scopes ;
@@ -819,6 +865,7 @@ export class GatewayClient {
819865 authBootstrapToken,
820866 authDeviceToken : shouldUseDeviceRetryToken ? ( storedToken ?? undefined ) : undefined ,
821867 authPassword,
868+ authApprovalRuntimeToken,
822869 signatureToken : authToken ?? authBootstrapToken ?? undefined ,
823870 resolvedDeviceToken,
824871 storedToken : storedToken ?? undefined ,
0 commit comments