← Back to PRs

#21682: fix(heartbeat): propagate sessionKey in exec/hooks to fix async context loss

by eviaaaaa open 2026-02-20 07:22 View on GitHub →
gateway agents size: XS
📝 Summary This PR is a clean re-implementation of the fix for asynchronous context loss. It addresses the issue where execution results and webhook wakes failed to reach users in non-main sessions (e.g., Discord threads, DMs, or Slack channels). > Note: This replaces PR #11888. Due to significant refactors in the upstream main branch, the previous implementation became obsolete. This PR re-applies the fix against the current codebase structure. 🔍 The Problem The root cause was that requestHeartbeatNow was frequently called without a sessionKey. In the current architecture, this caused the heartbeat system to: Default to the Main Session, leaving the actual target session queue un-flushed. Coalesce unrelated wake requests into a single generic 'default' wake, losing the specific session context required for directed routing. 🛠 Changes 1. Agents & Tools (agents/) bash-tools.exec-runtime.ts: Modified emitExecSystemEvent and maybeNotifyOnExit to strictly propagate the sessionKey when requesting a heartbeat after command completion or approval. 2. Gateway (gateway/) server-node-events.ts: Updated remote node event handlers (exec.started, exec.finished, exec.denied) to carry the originating sessionKey back to the heartbeat system. server/hooks.ts: Enhanced dispatchWakeHook to include the target sessionKey extracted from the wake request payload. 3. Testing (test/) server-node-events.test.ts: Updated test assertions to strictly verify that the sessionKey is correctly passed to the heartbeat mock. Regression Check: Verified that the "ghosting" issue in Discord is resolved by ensuring the wake-up signal is routed to the specific channel session. 🤖 AI/Vibe-Coding Transparency AI-Assisted: Yes Opencode (Gemini 3.1 Pro). Review: I have manually verified the propagation path from the tool execution layer to the gateway's event dispatcher. 🧪 Testing (Fully Verified) Manual Test: Confirmed in Discord that model responses now correctly appear in the specific channel/thread after an exec tool approval. Build & Lint: pnpm build && pnpm check (Fixed formatting in heartbeat-runner.ts). Status: Pass. Unit Tests: pnpm test. Status: Pass. (Added regression tests for coalescing). 💡 Why this matters This ensures the feedback loop for async actions is session-aware. Users in specialized sessions (Discord/Slack) will no longer be "ghosted" by the bot after long-running tasks or manual approvals. Fixes #14191 <!-- greptile_comment --> <h3>Greptile Summary</h3> This PR fixes async context loss in exec operations and webhook wakes by propagating `sessionKey` to the heartbeat system. The changes ensure that execution results and webhook notifications reach the correct session (Discord threads/DMs, Slack channels) instead of defaulting to the main session. The implementation adds `sessionKey` to four `requestHeartbeatNow` call sites: - `bash-tools.exec-runtime.ts`: propagates sessionKey on exec completion and exit notifications - `server-node-events.ts`: includes sessionKey from remote node exec events (started/finished/denied) - `server/hooks.ts`: passes sessionKey from wake hook dispatcher Test coverage is comprehensive, with all test assertions updated to verify sessionKey propagation. <h3>Confidence Score: 4/5</h3> - This PR is safe to merge with minimal risk - it's a targeted fix that adds proper context propagation without changing core logic - The changes are focused, well-tested, and address a specific bug. The implementation correctly propagates sessionKey through the call chain, and tests verify the behavior. Score reduced from 5 due to one observation: `dispatchAgentHook` in `hooks.ts` has two `requestHeartbeatNow` calls (lines 93, 101) that weren't updated with sessionKey. While events go to mainSessionKey, those heartbeats might also benefit from explicit sessionKey for consistency - though this may be intentional behavior for agent hooks vs wake hooks. - `src/gateway/server/hooks.ts` - verify whether `dispatchAgentHook` heartbeats on lines 93 and 101 should also include mainSessionKey <sub>Last reviewed commit: f96b4f3</sub> <!-- greptile_other_comments_section --> <sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub> <!-- /greptile_comment -->

Most Similar PRs