fix(heartbeat): propagate sessionKey in exec/hooks to fix async context loss
This commit fixes a critical issue where asynchronous execution results and webhook wakes were failing to reach users in non-main sessions (such as Discord threads, DMs, or Slack channels). The root cause was that `requestHeartbeatNow` was being called without a `sessionKey`. This caused the heartbeat system to: 1. Default to the Main Session. 2. Coalesce unrelated wake requests into a single generic 'default' wake, losing the specific session context needed to flush the event queue. Changes: - agents: `emitExecSystemEvent` now strictly propagates the `sessionKey` to `requestHeartbeatNow`. - gateway: `dispatchWakeHook` now includes the target `sessionKey` from the wake request. - gateway: Node events (`exec.started`, `exec.finished`, `exec.denied`) now carry the originating `sessionKey` to the heartbeat system. - test: Updated `server-node-events.test.ts` to assert that `sessionKey` is correctly passed when requesting heartbeats. # Conflicts: # src/agents/bash-tools.exec-runtime.ts # src/gateway/server-node-events.ts
This commit is contained in:
parent
218f8d74b6
commit
d57cbc5244
@ -154,14 +154,18 @@ describe("node exec events", () => {
|
||||
exitCode: 0,
|
||||
timedOut: false,
|
||||
output: "done",
|
||||
sessionKey: "agent:test:main",
|
||||
}),
|
||||
});
|
||||
|
||||
expect(enqueueSystemEventMock).toHaveBeenCalledWith(
|
||||
"Exec finished (node=node-2 id=run-2, code 0)\ndone",
|
||||
{ sessionKey: "node-node-2", contextKey: "exec:run-2" },
|
||||
{ sessionKey: "agent:test:main", contextKey: "exec:run-2" },
|
||||
);
|
||||
expect(requestHeartbeatNowMock).toHaveBeenCalledWith({ reason: "exec-event" });
|
||||
expect(requestHeartbeatNowMock).toHaveBeenCalledWith({
|
||||
reason: "exec-event",
|
||||
sessionKey: "agent:test:main",
|
||||
});
|
||||
});
|
||||
|
||||
it("suppresses noisy exec.finished success events with empty output", async () => {
|
||||
@ -189,6 +193,7 @@ describe("node exec events", () => {
|
||||
exitCode: 0,
|
||||
timedOut: false,
|
||||
output: "x".repeat(600),
|
||||
sessionKey: "agent:test:main",
|
||||
}),
|
||||
});
|
||||
|
||||
@ -197,7 +202,10 @@ describe("node exec events", () => {
|
||||
expect(text.startsWith("Exec finished (node=node-2 id=run-long, code 0)\n")).toBe(true);
|
||||
expect(text.endsWith("…")).toBe(true);
|
||||
expect(text.length).toBeLessThan(280);
|
||||
expect(requestHeartbeatNowMock).toHaveBeenCalledWith({ reason: "exec-event" });
|
||||
expect(requestHeartbeatNowMock).toHaveBeenCalledWith({
|
||||
reason: "exec-event",
|
||||
sessionKey: "agent:test:main",
|
||||
});
|
||||
});
|
||||
|
||||
it("enqueues exec.denied events with reason", async () => {
|
||||
|
||||
@ -37,7 +37,7 @@ export function createGatewayHooksRequestHandler(params: {
|
||||
const sessionKey = resolveMainSessionKeyFromConfig();
|
||||
enqueueSystemEvent(value.text, { sessionKey });
|
||||
if (value.mode === "now") {
|
||||
requestHeartbeatNow({ reason: "hook:wake" });
|
||||
requestHeartbeatNow({ reason: "hook:wake", sessionKey });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user