-
-
Notifications
You must be signed in to change notification settings - Fork 69.5k
Plugin typed hooks (api.on) don't fire across module bundle boundaries #23895
Description
Summary
Plugin hooks registered via api.on("before_reset", handler) never fire when the /new or /reset command is processed. The handler registers successfully (visible in openclaw plugins list as "loaded"), but hookRunner.hasHooks("before_reset") returns false at the call site.
Root Cause
The build system (Rolldown) creates separate module bundles that each have their own globalHookRunner singleton:
pi-embedded-CAmQsy9D.jsimportsgetGlobalHookRunnerfromdeliver-Vheuo8GO.jssubagent-registry-Bdm_X-N1.jsimportsgetGlobalHookRunnerfromdeliver-Day3efJ9.js
These are different files (43KB vs 45KB) with separate module-level globalHookRunner variables. When a plugin calls api.on("before_reset", handler), the typed hook is registered in one module's registry.typedHooks. But the /new command handler calls getGlobalHookRunner() from a different module's scope, where the hook runner was either never initialized or initialized with a different registry.
The internal hooks system (registerInternalHook / triggerInternalHook) works correctly because it shares state across module boundaries.
Reproduction
- Create a workspace plugin that uses
api.on("before_reset", handler)with aconsole.login the handler - Run
openclaw plugins list— plugin shows as "loaded" - Run
/newin any channel - Check logs — the handler never fires, no console output
Expected Behavior
api.on("before_reset") handlers should fire when /new or /reset is processed, regardless of which module bundle processes the command.
Workaround
Use workspace hooks (internal hooks system) instead of plugin typed hooks for command:new / command:reset events. This works because triggerInternalHook shares state across module boundaries.
Note: before_compaction and after_compaction have no internal hook equivalent, so plugins cannot reliably hook into compaction events.
Environment
- OpenClaw version: 2026.2.21 (npm)
- Node: v25.5.0
- OS: macOS (arm64)
- Build files examined:
pi-embedded-CAmQsy9D.js,subagent-registry-Bdm_X-N1.js,deliver-Vheuo8GO.js,deliver-Day3efJ9.js