From 0d8beeb4e5f52302557abd2c667d658c185f7fba Mon Sep 17 00:00:00 2001 From: Eric Lytle Date: Mon, 2 Mar 2026 23:25:31 +0000 Subject: [PATCH] fix(hooks): use globalThis singleton for handler registry to survive bundle splitting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this fix, the bundler can emit multiple copies of internal-hooks into separate chunks. registerInternalHook writes to one Map instance while triggerInternalHook reads from another — resulting in hooks that silently fire with zero handlers regardless of how many were registered. Reproduce: load a hook via hooks.external.entries (loader reads one chunk), then send a message:transcribed event (get-reply imports a different chunk). The handler list is empty; the hook never runs. Fix: use globalThis.__openclaw_internal_hook_handlers__ as a shared singleton. All module copies check for and reuse the same Map, ensuring registrations are always visible to triggers. --- src/hooks/internal-hooks.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/hooks/internal-hooks.ts b/src/hooks/internal-hooks.ts index 4a29acb8b..08a642a17 100644 --- a/src/hooks/internal-hooks.ts +++ b/src/hooks/internal-hooks.ts @@ -200,8 +200,23 @@ export interface InternalHookEvent { export type InternalHookHandler = (event: InternalHookEvent) => Promise | void; -/** Registry of hook handlers by event key */ -const handlers = new Map(); +/** + * Registry of hook handlers by event key. + * + * Uses a globalThis singleton so that registerInternalHook and + * triggerInternalHook always share the same Map even when the bundler + * emits multiple copies of this module into separate chunks (bundle + * splitting). Without the singleton, handlers registered in one chunk + * are invisible to triggerInternalHook in another chunk, causing hooks + * to silently fire with zero handlers. + */ +const _g = globalThis as typeof globalThis & { + __openclaw_internal_hook_handlers__?: Map; +}; +if (!_g.__openclaw_internal_hook_handlers__) { + _g.__openclaw_internal_hook_handlers__ = new Map(); +} +const handlers = _g.__openclaw_internal_hook_handlers__; const log = createSubsystemLogger("internal-hooks"); /**