#19464: feat(plugins): expose requestHeartbeatNow on plugin runtime
channel: bluebubbles
size: XS
Cluster:
Plugin Enhancements and Fixes
## 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
#22283: Plugins: expose resolveMainSessionKey in runtime system
by MegaPhoenix92 · 2026-02-21
77.2%
#16044: plugin-sdk: expose onAgentEvent + onSessionTranscriptUpdate via Plu...
by scifantastic · 2026-02-14
76.3%
#19270: fix: retry event-driven heartbeats blocked by requests-in-flight
by deggertsen · 2026-02-17
72.2%
#19745: fix(heartbeat): enforce interval check regardless of trigger source
by misterdas · 2026-02-18
69.8%
#14241: fix(heartbeat): propagate originating session key for exec event qu...
by aldoeliacim · 2026-02-11
69.6%
#11732: feat(plugins): add injectMessages to before_agent_start hook
by antra-tess · 2026-02-08
69.5%
#21851: fix: drain pending system events when main command lane goes idle
by alan-purring · 2026-02-20
69.4%
#17801: fix(heartbeat): enforce interval guard for non-interval wake reasons
by aldoeliacim · 2026-02-16
69.3%
#22624: feat(plugins): add before_context_send hook and model routing via b...
by davidrudduck · 2026-02-21
69.3%
#11124: feat(plugins): add before_llm_request hook for custom LLM headers
by johnlanni · 2026-02-07
68.3%