← Back to PRs

#11681: feat(plugins): add cancel support to message_received hook

by PrimeTenet open 2026-02-08 04:55 View on GitHub →
stale
## Summary Enables plugins to block inbound messages by returning `{ cancel: true }` from the `message_received` hook, matching the existing `message_sending` cancel behavior. ## Changes **3 files changed:** - `src/plugins/types.ts` - Add `PluginHookMessageReceivedResult` type with `cancel` field - `src/plugins/hooks.ts` - Collect results from parallel hook execution, return `{ cancel: true }` if any hook cancelled - `src/auto-reply/reply/dispatch-from-config.ts` - Await hook results and stop processing if message marked for cancel ## Usage api.on('message_received', async (event, ctx) => { if (containsThreat(event.content)) { return { cancel: true }; // Block the message } // Allow through }, { priority: 100 }); ## Use Cases - Security/DLP plugins blocking malicious content - Content moderation (spam, abuse) - Rate limiting excessive messages - Access control ## Behavior - Hooks run in **parallel** (preserves existing `Promise.all` behavior) - If **any** hook returns `{ cancel: true }`, message is blocked - Dispatcher now **awaits** hook results to check cancel flag (was fire-and-forget) ## Breaking Changes **Latency impact:** Messages now wait for all `message_received` hooks to complete before processing (was fire-and-forget). Adds ~10ms latency per message if hooks are present. Plugins should be optimized for fast execution (<10ms recommended). ## Backward Compatibility Existing `message_received` hooks that return `void` continue to work unchanged. <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> Adds a cancellable return type for the `message_received` plugin hook (`{ cancel?: boolean }`), updates the hook runner to execute all `message_received` handlers in parallel and aggregate their results, and changes the config-based dispatcher to await `message_received` hooks and stop further processing when any hook cancels. This fits into the existing plugin hook system by extending the hook type map in `src/plugins/types.ts` and exposing the new result type via `src/plugins/hooks.ts`, then consuming the cancel result in the inbound message dispatch path. <h3>Confidence Score: 3/5</h3> - This PR is close to mergeable but has a cancel-path lifecycle/diagnostics bug that should be fixed first. - Core typing and hook aggregation look consistent, but early-return on cancel bypasses existing message processing/idle tracking in the dispatcher, which can break diagnostics/session state accounting. There’s also a behavior change (message_received now blocks) that should be made consistent with expectations across the codebase. - src/auto-reply/reply/dispatch-from-config.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs