← Back to PRs

#19464: feat(plugins): expose requestHeartbeatNow on plugin runtime

by AustinEral open 2026-02-17 20:49 View on GitHub →
channel: bluebubbles size: XS
## Summary Extensions can inject system events via `runtime.system.enqueueSystemEvent`, but there's no clean way to wake the agent immediately afterward. The agent won't process the event until the next heartbeat cycle. `requestHeartbeatNow` already exists internally and is used by cron, exec, and node-events — this PR exposes it on `PluginRuntime.system` so extensions can use it too. ## Use case Any extension handling async inbound events (webhook callbacks, relay messages, device notifications, etc.) that needs the agent to process them promptly: ```typescript runtime.system.enqueueSystemEvent(eventText, { sessionKey }); runtime.system.requestHeartbeatNow({ reason: "my-extension" }); ``` ## Changes **`src/plugins/runtime/types.ts`** - Add `RequestHeartbeatNow` type alias - Add `requestHeartbeatNow` to `PluginRuntime.system` **`src/plugins/runtime/index.ts`** - Import `requestHeartbeatNow` from `../../infra/heartbeat-wake.js` - Wire into `createPluginRuntime()` 2 files, 4 lines added. No breaking changes — purely additive. ## Testing - TypeScript check: zero new errors (pre-existing Twitch/UI dep errors only) - Test suite: 6990 passed, 2 failed (pre-existing, unrelated — Discord voice + Telegram album) - Tested on a live OpenClaw instance with a custom extension using both `enqueueSystemEvent` + `requestHeartbeatNow` --- 🤖 AI-assisted (Claude) — fully tested, change is minimal and well-understood. <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR exposes the existing `requestHeartbeatNow` function from `src/infra/heartbeat-wake.ts` on the `PluginRuntime.system` API surface, enabling plugins/extensions to trigger an immediate agent heartbeat after calling `enqueueSystemEvent`. The change mirrors precisely how internal callers (cron, exec-runtime, node-events, hooks) already use the function. - `src/plugins/runtime/types.ts`: adds `RequestHeartbeatNow` type alias (using the same `typeof import(...)` pattern as every other type in the file) and adds `requestHeartbeatNow: RequestHeartbeatNow` to the `system` namespace. - `src/plugins/runtime/index.ts`: imports `requestHeartbeatNow` from `../../infra/heartbeat-wake.js` and wires it into `createPluginRuntime()`, adjacent to the already-exposed `enqueueSystemEvent`. - `extensions/bluebubbles/src/monitor.test.ts`: adds the required `vi.fn()` stub to the `createMockRuntime()` factory so the test continues to satisfy the `PluginRuntime` shape — a necessary and correct change. No breaking changes; the addition is purely additive and follows every existing convention in the file. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge; it is a purely additive, minimal exposure of an already battle-tested internal function. - The function being exposed (`requestHeartbeatNow`) already exists and is used by multiple trusted internal callers with the same call pattern the plugin API now enables. The type definition follows the established `typeof import(...)` convention. The runtime wiring is a single line addition next to the already-exposed `enqueueSystemEvent`. The test mock update is mechanically correct. No new logic is introduced, no interfaces are changed in a breaking way, and the PR description accurately describes the change. - No files require special attention. <sub>Last reviewed commit: 53a3b2e</sub> <!-- 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