From f5bedd1736b1f69ea9f739522c233af19ea119c1 Mon Sep 17 00:00:00 2001 From: WallaceSociety Date: Thu, 29 Jan 2026 06:35:26 -0500 Subject: [PATCH] Fix bug where plugin hooks register but do not fire --- src/plugins/hook-runner-global.ts | 6 ++-- src/plugins/registry.ts | 57 ++++++++++++++++++++----------- src/plugins/types.ts | 18 ++++++++++ 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/src/plugins/hook-runner-global.ts b/src/plugins/hook-runner-global.ts index 368d76684..7fef60aec 100644 --- a/src/plugins/hook-runner-global.ts +++ b/src/plugins/hook-runner-global.ts @@ -29,9 +29,9 @@ export function initializeGlobalHookRunner(registry: PluginRegistry): void { catchErrors: true, }); - const hookCount = registry.hooks.length; - if (hookCount > 0) { - log.info(`hook runner initialized with ${hookCount} registered hooks`); + const typedHookCount = registry.typedHooks.length; + if (typedHookCount > 0) { + log.info(`hook runner initialized with ${typedHookCount} registered hooks`); } } diff --git a/src/plugins/registry.ts b/src/plugins/registry.ts index 226f6e496..b5721dd7d 100644 --- a/src/plugins/registry.ts +++ b/src/plugins/registry.ts @@ -7,26 +7,27 @@ import type { } from "../gateway/server-methods/types.js"; import { registerInternalHook } from "../hooks/internal-hooks.js"; import { resolveUserPath } from "../utils.js"; -import type { - MoltbotPluginApi, - MoltbotPluginChannelRegistration, - MoltbotPluginCliRegistrar, - MoltbotPluginCommandDefinition, - MoltbotPluginHttpHandler, - MoltbotPluginHttpRouteHandler, - MoltbotPluginHookOptions, - ProviderPlugin, - MoltbotPluginService, - MoltbotPluginToolContext, - MoltbotPluginToolFactory, - PluginConfigUiHint, - PluginDiagnostic, - PluginLogger, - PluginOrigin, - PluginKind, - PluginHookName, - PluginHookHandlerMap, - PluginHookRegistration as TypedPluginHookRegistration, +import { + TYPED_HOOK_NAMES, + type MoltbotPluginApi, + type MoltbotPluginChannelRegistration, + type MoltbotPluginCliRegistrar, + type MoltbotPluginCommandDefinition, + type MoltbotPluginHttpHandler, + type MoltbotPluginHttpRouteHandler, + type MoltbotPluginHookOptions, + type ProviderPlugin, + type MoltbotPluginService, + type MoltbotPluginToolContext, + type MoltbotPluginToolFactory, + type PluginConfigUiHint, + type PluginDiagnostic, + type PluginLogger, + type PluginOrigin, + type PluginKind, + type PluginHookName, + type PluginHookHandlerMap, + type PluginHookRegistration as TypedPluginHookRegistration, } from "./types.js"; import { registerPluginCommand } from "./commands.js"; import type { PluginRuntime } from "./runtime/types.js"; @@ -252,6 +253,22 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) { source: record.source, }); + // Bridge to typed hooks: if any event matches a PluginHookName, also register + // in typedHooks so the hook runner can find it. This allows plugins to use + // either api.registerHook() or api.on() for typed hooks like message_received. + for (const event of normalizedEvents) { + if (TYPED_HOOK_NAMES.has(event as PluginHookName)) { + registry.typedHooks.push({ + pluginId: record.id, + hookName: event as PluginHookName, + handler: handler as unknown as PluginHookHandlerMap[PluginHookName], + priority: opts?.priority, + source: record.source, + } as TypedPluginHookRegistration); + record.hookCount += 1; + } + } + const hookSystemEnabled = config?.hooks?.internal?.enabled === true; if (!hookSystemEnabled || opts?.register === false) { return; diff --git a/src/plugins/types.ts b/src/plugins/types.ts index f9aaa5709..a77d6c694 100644 --- a/src/plugins/types.ts +++ b/src/plugins/types.ts @@ -81,6 +81,7 @@ export type MoltbotPluginHookOptions = { name?: string; description?: string; register?: boolean; + priority?: number; }; export type ProviderAuthKind = "oauth" | "api_key" | "token" | "device_code" | "custom"; @@ -302,6 +303,23 @@ export type PluginHookName = | "gateway_start" | "gateway_stop"; +export const TYPED_HOOK_NAMES: Set = new Set([ + "before_agent_start", + "agent_end", + "before_compaction", + "after_compaction", + "message_received", + "message_sending", + "message_sent", + "before_tool_call", + "after_tool_call", + "tool_result_persist", + "session_start", + "session_end", + "gateway_start", + "gateway_stop", +]); + // Agent context shared across agent hooks export type PluginHookAgentContext = { agentId?: string;