@@ -18,16 +18,17 @@ import {
1818import type { SafeGatewayRestartRequestResult } from "../../infra/restart-coordinator.js" ;
1919import { type GatewayRestartIntent , writeGatewayRestartIntentSync } from "../../infra/restart.js" ;
2020import { defaultRuntime } from "../../runtime.js" ;
21+ import { createLazyImportLoader } from "../../shared/lazy-promise.js" ;
2122import { formatCliCommand } from "../command-format.js" ;
2223import { parseDurationMs } from "../parse-duration.js" ;
2324import { recoverInstalledLaunchAgent } from "./launchd-recovery.js" ;
24- import { createNullWriter } from "./response.js" ;
2525import {
2626 runServiceRestart ,
2727 runServiceStart ,
2828 runServiceStop ,
2929 runServiceUninstall ,
3030} from "./lifecycle-core.js" ;
31+ import { createNullWriter } from "./response.js" ;
3132import {
3233 DEFAULT_RESTART_HEALTH_ATTEMPTS ,
3334 DEFAULT_RESTART_HEALTH_DELAY_MS ,
@@ -45,6 +46,18 @@ import type { DaemonLifecycleOptions } from "./types.js";
4546const POST_RESTART_HEALTH_ATTEMPTS = DEFAULT_RESTART_HEALTH_ATTEMPTS ;
4647const POST_RESTART_HEALTH_DELAY_MS = DEFAULT_RESTART_HEALTH_DELAY_MS ;
4748const WINDOWS_POST_RESTART_HEALTH_TIMEOUT_MS = 180_000 ;
49+ const gatewayProbeAuthModuleLoader = createLazyImportLoader (
50+ ( ) => import ( "../../gateway/probe-auth.js" ) ,
51+ ) ;
52+
53+ type GatewayProbeAuthResolution = {
54+ auth : { token ?: string ; password ?: string } ;
55+ warning ?: string ;
56+ } ;
57+
58+ function loadGatewayProbeAuthModule ( ) {
59+ return gatewayProbeAuthModuleLoader . load ( ) ;
60+ }
4861
4962function postRestartHealthAttempts ( ) : number {
5063 return process . platform === "win32"
@@ -89,13 +102,38 @@ function resolveGatewayPortFallback(): Promise<number> {
89102 . catch ( ( ) => resolveGatewayPort ( undefined , process . env ) ) ;
90103}
91104
92- async function assertUnmanagedGatewayRestartEnabled ( port : number ) : Promise < void > {
105+ async function resolveGatewayRestartConfigContext ( ) : Promise < {
106+ cfg : Awaited < ReturnType < typeof readBestEffortConfig > > | undefined ;
107+ probeAuth ?: GatewayProbeAuthResolution ;
108+ } > {
93109 const cfg = await readBestEffortConfig ( ) . catch ( ( ) => undefined ) ;
110+ return {
111+ cfg,
112+ probeAuth : cfg
113+ ? await loadGatewayProbeAuthModule ( )
114+ . then ( ( { resolveGatewayProbeAuthSafeWithSecretInputs } ) =>
115+ resolveGatewayProbeAuthSafeWithSecretInputs ( {
116+ cfg,
117+ mode : "local" ,
118+ env : process . env ,
119+ } ) ,
120+ )
121+ . catch ( ( ) => undefined )
122+ : undefined ,
123+ } ;
124+ }
125+
126+ async function assertUnmanagedGatewayRestartEnabled ( params : {
127+ port : number ;
128+ cfg ?: Awaited < ReturnType < typeof readBestEffortConfig > > ;
129+ probeAuth ?: GatewayProbeAuthResolution ;
130+ } ) : Promise < void > {
131+ const cfg = params . cfg ;
94132 const tlsEnabled = Boolean ( cfg ?. gateway ?. tls ?. enabled ) ;
95133 const scheme = tlsEnabled ? "wss" : "ws" ;
96134 const probe = await probeGateway ( {
97- url : `${ scheme } ://127.0.0.1:${ port } ` ,
98- auth : {
135+ url : `${ scheme } ://127.0.0.1:${ params . port } ` ,
136+ auth : params . probeAuth ?. auth ?? {
99137 token : normalizeOptionalString ( process . env . OPENCLAW_GATEWAY_TOKEN ) ,
100138 password : normalizeOptionalString ( process . env . OPENCLAW_GATEWAY_PASSWORD ) ,
101139 } ,
@@ -230,12 +268,16 @@ async function requestSafeGatewayRestart(opts: DaemonLifecycleOptions): Promise<
230268async function restartGatewayWithoutServiceManager (
231269 port : number ,
232270 restartIntent ?: GatewayRestartIntent ,
271+ context ?: {
272+ cfg ?: Awaited < ReturnType < typeof readBestEffortConfig > > ;
273+ probeAuth ?: GatewayProbeAuthResolution ;
274+ } ,
233275) {
234276 const managed = await handleSystemScopeSystemdGateway ( "restart" ) ;
235277 if ( managed ) {
236278 return managed ;
237279 }
238- await assertUnmanagedGatewayRestartEnabled ( port ) ;
280+ await assertUnmanagedGatewayRestartEnabled ( { port, ... context } ) ;
239281 const pids = resolveVerifiedGatewayListenerPids ( port ) ;
240282 if ( pids . length === 0 ) {
241283 return null ;
@@ -325,6 +367,10 @@ export async function runDaemonRestart(opts: DaemonLifecycleOptions = {}): Promi
325367 const restartPort = await resolveGatewayLifecyclePort ( service ) . catch ( ( ) =>
326368 resolveGatewayPortFallback ( ) ,
327369 ) ;
370+ let restartContextPromise :
371+ | Promise < Awaited < ReturnType < typeof resolveGatewayRestartConfigContext > > >
372+ | undefined ;
373+ const getRestartContext = ( ) => ( restartContextPromise ??= resolveGatewayRestartConfigContext ( ) ) ;
328374 const restartHealthAttempts = postRestartHealthAttempts ( ) ;
329375 const restartWaitMs = restartHealthAttempts * POST_RESTART_HEALTH_DELAY_MS ;
330376 const restartWaitSeconds = Math . round ( restartWaitMs / 1000 ) ;
@@ -345,7 +391,11 @@ export async function runDaemonRestart(opts: DaemonLifecycleOptions = {}): Promi
345391 return recovered ;
346392 }
347393 }
348- const handled = await restartGatewayWithoutServiceManager ( restartPort , restartIntent ) ;
394+ const handled = await restartGatewayWithoutServiceManager (
395+ restartPort ,
396+ restartIntent ,
397+ await getRestartContext ( ) ,
398+ ) ;
349399 if ( handled ) {
350400 restartedWithoutServiceManager = true ;
351401 return handled ;
@@ -354,10 +404,12 @@ export async function runDaemonRestart(opts: DaemonLifecycleOptions = {}): Promi
354404 } ,
355405 postRestartCheck : async ( { warnings, fail, stdout } ) => {
356406 if ( restartedWithoutServiceManager ) {
407+ const restartContext = await getRestartContext ( ) ;
357408 const health = await waitForGatewayHealthyListener ( {
358409 port : restartPort ,
359410 attempts : restartHealthAttempts ,
360411 delayMs : POST_RESTART_HEALTH_DELAY_MS ,
412+ auth : restartContext . probeAuth ?. auth ,
361413 } ) ;
362414 if ( health . healthy ) {
363415 return undefined ;
0 commit comments