From f41bdf3c543a2ad83ada19492963f38d85cfe7f1 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Tue, 24 Mar 2026 11:07:37 -0700 Subject: [PATCH] refactor(plugins): make hook runner global lazy --- src/plugins/hook-runner-global.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/plugins/hook-runner-global.ts b/src/plugins/hook-runner-global.ts index 43d212025e7..cef104b34e5 100644 --- a/src/plugins/hook-runner-global.ts +++ b/src/plugins/hook-runner-global.ts @@ -11,24 +11,27 @@ import { createHookRunner, type HookRunner } from "./hooks.js"; import type { PluginRegistry } from "./registry.js"; import type { PluginHookGatewayContext, PluginHookGatewayStopEvent } from "./types.js"; -const log = createSubsystemLogger("plugins"); - type HookRunnerGlobalState = { hookRunner: HookRunner | null; registry: PluginRegistry | null; }; const hookRunnerGlobalStateKey = Symbol.for("openclaw.plugins.hook-runner-global-state"); -const state = resolveGlobalSingleton(hookRunnerGlobalStateKey, () => ({ - hookRunner: null, - registry: null, -})); +const getState = () => + resolveGlobalSingleton(hookRunnerGlobalStateKey, () => ({ + hookRunner: null, + registry: null, + })); + +const getLog = () => createSubsystemLogger("plugins"); /** * Initialize the global hook runner with a plugin registry. * Called once when plugins are loaded during gateway startup. */ export function initializeGlobalHookRunner(registry: PluginRegistry): void { + const state = getState(); + const log = getLog(); state.registry = registry; state.hookRunner = createHookRunner(registry, { logger: { @@ -50,7 +53,7 @@ export function initializeGlobalHookRunner(registry: PluginRegistry): void { * Returns null if plugins haven't been loaded yet. */ export function getGlobalHookRunner(): HookRunner | null { - return state.hookRunner; + return getState().hookRunner; } /** @@ -58,14 +61,14 @@ export function getGlobalHookRunner(): HookRunner | null { * Returns null if plugins haven't been loaded yet. */ export function getGlobalPluginRegistry(): PluginRegistry | null { - return state.registry; + return getState().registry; } /** * Check if any hooks are registered for a given hook name. */ export function hasGlobalHooks(hookName: Parameters[0]): boolean { - return state.hookRunner?.hasHooks(hookName) ?? false; + return getState().hookRunner?.hasHooks(hookName) ?? false; } export async function runGlobalGatewayStopSafely(params: { @@ -73,6 +76,7 @@ export async function runGlobalGatewayStopSafely(params: { ctx: PluginHookGatewayContext; onError?: (err: unknown) => void; }): Promise { + const log = getLog(); const hookRunner = getGlobalHookRunner(); if (!hookRunner?.hasHooks("gateway_stop")) { return; @@ -92,6 +96,7 @@ export async function runGlobalGatewayStopSafely(params: { * Reset the global hook runner (for testing). */ export function resetGlobalHookRunner(): void { + const state = getState(); state.hookRunner = null; state.registry = null; }