@@ -79,6 +79,8 @@ type DaemonClientSettings = {
7979 remoteAuthToken ?: string ;
8080} ;
8181
82+ type ResolvedDaemonTransport = 'socket' | 'http' ;
83+
8284const REQUEST_TIMEOUT_MS = resolveDaemonRequestTimeoutMs ( ) ;
8385const DAEMON_STARTUP_TIMEOUT_MS = resolveDaemonStartupTimeoutMs ( ) ;
8486const DAEMON_STARTUP_ATTEMPTS = resolveDaemonStartupAttempts ( ) ;
@@ -532,25 +534,44 @@ async function stopDaemonProcessForTakeover(info: DaemonInfo): Promise<void> {
532534}
533535
534536function readDaemonInfo ( infoPath : string ) : DaemonInfo | null {
535- const data = readJsonFile ( infoPath ) as DaemonInfo | null ;
536- if ( ! data || typeof data . token !== 'string' || data . token . length === 0 ) return null ;
537- const hasSocket = Number . isInteger ( data . port ) && Number ( data . port ) > 0 ;
538- const hasHttp = Number . isInteger ( data . httpPort ) && Number ( data . httpPort ) > 0 ;
537+ const data = readJsonFile ( infoPath ) ;
538+ if ( ! data || typeof data !== 'object' ) return null ;
539+ const parsed = data as Partial < DaemonInfo > ;
540+ const token = typeof parsed . token === 'string' && parsed . token . length > 0 ? parsed . token : null ;
541+ if ( ! token ) return null ;
542+ const hasSocket = Number . isInteger ( parsed . port ) && Number ( parsed . port ) > 0 ;
543+ const hasHttp = Number . isInteger ( parsed . httpPort ) && Number ( parsed . httpPort ) > 0 ;
539544 if ( ! hasSocket && ! hasHttp ) return null ;
545+ const transport = parsed . transport ;
546+ const version = typeof parsed . version === 'string' ? parsed . version : undefined ;
547+ const codeSignature = typeof parsed . codeSignature === 'string' ? parsed . codeSignature : undefined ;
548+ const processStartTime = typeof parsed . processStartTime === 'string' ? parsed . processStartTime : undefined ;
549+ const hasPid = Number . isInteger ( parsed . pid ) && Number ( parsed . pid ) > 0 ;
540550 return {
541- ...data ,
542- port : hasSocket ? Number ( data . port ) : undefined ,
543- httpPort : hasHttp ? Number ( data . httpPort ) : undefined ,
544- pid : Number . isInteger ( data . pid ) && data . pid > 0 ? data . pid : 0 ,
551+ token,
552+ port : hasSocket ? Number ( parsed . port ) : undefined ,
553+ httpPort : hasHttp ? Number ( parsed . httpPort ) : undefined ,
554+ transport : transport === 'socket' || transport === 'http' || transport === 'dual' ? transport : undefined ,
555+ pid : hasPid ? Number ( parsed . pid ) : 0 ,
556+ version,
557+ codeSignature,
558+ processStartTime,
545559 } ;
546560}
547561
548562function readDaemonLockInfo ( lockPath : string ) : DaemonLockInfo | null {
549- const data = readJsonFile ( lockPath ) as DaemonLockInfo | null ;
550- if ( ! data || ! Number . isInteger ( data . pid ) || data . pid <= 0 ) {
563+ const data = readJsonFile ( lockPath ) ;
564+ if ( ! data || typeof data !== 'object' ) return null ;
565+ const parsed = data as Partial < DaemonLockInfo > ;
566+ const hasPid = Number . isInteger ( parsed . pid ) && Number ( parsed . pid ) > 0 ;
567+ if ( ! hasPid ) {
551568 return null ;
552569 }
553- return data ;
570+ return {
571+ pid : Number ( parsed . pid ) ,
572+ processStartTime : typeof parsed . processStartTime === 'string' ? parsed . processStartTime : undefined ,
573+ startedAt : typeof parsed . startedAt === 'number' ? parsed . startedAt : undefined ,
574+ } ;
554575}
555576
556577function removeDaemonInfo ( infoPath : string ) : void {
@@ -720,7 +741,7 @@ async function sendRequest(
720741 return await sendSocketRequest ( info , req ) ;
721742}
722743
723- function chooseTransport ( info : DaemonInfo , preference : DaemonTransportPreference ) : 'socket' | 'http' {
744+ function chooseTransport ( info : DaemonInfo , preference : DaemonTransportPreference ) : ResolvedDaemonTransport {
724745 if ( info . baseUrl ) {
725746 // Defensive guard: resolveClientSettings rejects this earlier for normal CLI flow.
726747 if ( preference === 'socket' ) {
@@ -730,22 +751,29 @@ function chooseTransport(info: DaemonInfo, preference: DaemonTransportPreference
730751 }
731752 return 'http' ;
732753 }
733- if ( preference === 'http' ) {
734- if ( ! info . httpPort ) throw new AppError ( 'COMMAND_FAILED' , 'Daemon HTTP endpoint is unavailable' ) ;
735- return 'http' ;
736- }
737- if ( preference === 'socket' ) {
738- if ( ! info . port ) throw new AppError ( 'COMMAND_FAILED' , 'Daemon socket endpoint is unavailable' ) ;
739- return 'socket' ;
754+ if ( preference === 'http' || preference === 'socket' ) {
755+ return requireDaemonTransport ( info , preference ) ;
740756 }
741- const transport = info . transport ;
742- if ( transport === 'http' && info . httpPort ) return 'http' ;
743- if ( ( transport === 'socket' || transport === 'dual' ) && info . port ) return ' socket';
744- if ( info . httpPort ) return 'http' ;
745- if ( info . port ) return 'socket' ;
757+ const autoOrder : ResolvedDaemonTransport [ ] = info . transport === 'socket' || info . transport === 'dual'
758+ ? [ 'socket' , 'http' ]
759+ : [ 'http' , ' socket'] ;
760+ const available = autoOrder . find ( ( transport ) => hasDaemonTransport ( info , transport ) ) ;
761+ if ( available ) return available ;
746762 throw new AppError ( 'COMMAND_FAILED' , 'Daemon metadata has no reachable transport' ) ;
747763}
748764
765+ function hasDaemonTransport ( info : DaemonInfo , transport : ResolvedDaemonTransport ) : boolean {
766+ return transport === 'http' ? Boolean ( info . httpPort ) : Boolean ( info . port ) ;
767+ }
768+
769+ function requireDaemonTransport ( info : DaemonInfo , transport : ResolvedDaemonTransport ) : ResolvedDaemonTransport {
770+ if ( hasDaemonTransport ( info , transport ) ) return transport ;
771+ throw new AppError (
772+ 'COMMAND_FAILED' ,
773+ transport === 'http' ? 'Daemon HTTP endpoint is unavailable' : 'Daemon socket endpoint is unavailable' ,
774+ ) ;
775+ }
776+
749777async function sendSocketRequest ( info : DaemonInfo , req : DaemonRequest ) : Promise < DaemonResponse > {
750778 const port = info . port ;
751779 if ( ! port ) throw new AppError ( 'COMMAND_FAILED' , 'Daemon socket endpoint is unavailable' ) ;
0 commit comments