@@ -181,6 +181,9 @@ function injectAuthProfile(logger: { info: (msg: string) => void }): void {
181181 }
182182}
183183
184+ // Store active proxy handle for cleanup on gateway_stop
185+ let activeProxyHandle : Awaited < ReturnType < typeof startProxy > > | null = null ;
186+
184187/**
185188 * Start the x402 proxy in the background.
186189 * Called from register() because OpenClaw's loader only invokes register(),
@@ -249,6 +252,7 @@ async function startProxyInBackground(api: OpenClawPluginApi): Promise<void> {
249252 } ) ;
250253
251254 setActiveProxy ( proxy ) ;
255+ activeProxyHandle = proxy ;
252256 api . logger . info ( `BlockRun provider active — ${ proxy . baseUrl } /v1 (smart routing enabled)` ) ;
253257}
254258
@@ -298,7 +302,22 @@ const plugin: OpenClawPluginDefinition = {
298302 if ( ! defaults . model ) defaults . model = { } ;
299303 ( defaults . model as Record < string , unknown > ) . primary = "blockrun/auto" ;
300304
301- api . logger . info ( "BlockRun provider registered (default: blockrun/auto)" ) ;
305+ api . logger . info ( "BlockRun provider registered (30+ models via x402)" ) ;
306+
307+ // Register cleanup hook for gateway hot restarts (prevents EADDRINUSE on port 8402)
308+ api . on ( "gateway_stop" , async ( ) => {
309+ if ( activeProxyHandle ) {
310+ try {
311+ await activeProxyHandle . close ( ) ;
312+ api . logger . info ( "BlockRun proxy closed for gateway restart" ) ;
313+ } catch ( err ) {
314+ api . logger . warn (
315+ `Failed to close proxy: ${ err instanceof Error ? err . message : String ( err ) } ` ,
316+ ) ;
317+ }
318+ activeProxyHandle = null ;
319+ }
320+ } ) ;
302321
303322 // Start x402 proxy in background (fire-and-forget)
304323 // OpenClaw only calls register(), not activate() — so all init goes here.
0 commit comments