Skip to content

Commit 8aace2b

Browse files
committed
fix(regression): hydrate node tool event metadata
1 parent 72ba2b3 commit 8aace2b

2 files changed

Lines changed: 68 additions & 1 deletion

File tree

src/gateway/server-chat.agent-events.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,69 @@ describe("agent event handler", () => {
781781
resetAgentRunContextForTest();
782782
});
783783

784+
it("hydrates node session tool events with session ownership metadata", () => {
785+
const { nodeSendToSession, handler } = createHarness({
786+
resolveSessionKeyForRun: () => "session-1",
787+
});
788+
789+
vi.mocked(loadGatewaySessionRow).mockReturnValue({
790+
key: "session-1",
791+
kind: "direct",
792+
spawnedBy: "agent:main:main",
793+
spawnedWorkspaceDir: "/tmp/subagent",
794+
forkedFromParent: true,
795+
spawnDepth: 2,
796+
subagentRole: "orchestrator",
797+
subagentControlScope: "children",
798+
lastThreadId: 42,
799+
fastMode: true,
800+
verboseLevel: "on",
801+
updatedAt: 1_200,
802+
});
803+
804+
registerAgentRunContext("run-tool-node", { sessionKey: "session-1", verboseLevel: "on" });
805+
806+
handler({
807+
runId: "run-tool-node",
808+
seq: 1,
809+
stream: "tool",
810+
ts: 1_234,
811+
data: {
812+
phase: "start",
813+
name: "exec",
814+
toolCallId: "tool-node-1",
815+
args: { command: "echo hi" },
816+
},
817+
});
818+
819+
expect(nodeSendToSession).toHaveBeenCalledWith(
820+
"session-1",
821+
"agent",
822+
expect.objectContaining({
823+
runId: "run-tool-node",
824+
sessionKey: "session-1",
825+
spawnedBy: "agent:main:main",
826+
spawnedWorkspaceDir: "/tmp/subagent",
827+
forkedFromParent: true,
828+
spawnDepth: 2,
829+
subagentRole: "orchestrator",
830+
subagentControlScope: "children",
831+
lastThreadId: 42,
832+
fastMode: true,
833+
verboseLevel: "on",
834+
stream: "tool",
835+
ts: 1_234,
836+
data: expect.objectContaining({
837+
phase: "start",
838+
name: "exec",
839+
toolCallId: "tool-node-1",
840+
args: { command: "echo hi" },
841+
}),
842+
}),
843+
);
844+
resetAgentRunContextForTest();
845+
});
846+
784847
it("broadcasts terminal session status to session subscribers on lifecycle end", () => {
785848
const { broadcastToConnIds, sessionEventSubscribers, handler } = createHarness({
786849
resolveSessionKeyForRun: () => "session-finished",

src/gateway/server-chat.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,11 @@ export function createAgentEventHandler({
803803
// Send tool events to node/channel subscribers only when verbose is enabled;
804804
// WS clients already received the event above via broadcastToConnIds.
805805
if (!isToolEvent || toolVerbose !== "off") {
806-
nodeSendToSession(sessionKey, "agent", isToolEvent ? toolPayload : agentPayload);
806+
nodeSendToSession(
807+
sessionKey,
808+
"agent",
809+
isToolEvent ? { ...toolPayload, ...buildSessionEventSnapshot(sessionKey) } : agentPayload,
810+
);
807811
}
808812
if (!isAborted && evt.stream === "assistant" && typeof evt.data?.text === "string") {
809813
emitChatDelta(sessionKey, clientRunId, evt.runId, evt.seq, evt.data.text, evt.data.delta);

0 commit comments

Comments
 (0)