Skip to content

Commit e890cde

Browse files
committed
fix(regression): hydrate run-scoped tool event metadata
1 parent c42ec81 commit e890cde

2 files changed

Lines changed: 70 additions & 1 deletion

File tree

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

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,71 @@ describe("agent event handler", () => {
716716
resetAgentRunContextForTest();
717717
});
718718

719+
it("hydrates run-scoped tool events with session ownership metadata", () => {
720+
const { broadcastToConnIds, toolEventRecipients, handler } = createHarness({
721+
resolveSessionKeyForRun: () => "session-1",
722+
});
723+
724+
vi.mocked(loadGatewaySessionRow).mockReturnValue({
725+
key: "session-1",
726+
kind: "direct",
727+
spawnedBy: "agent:main:main",
728+
spawnedWorkspaceDir: "/tmp/subagent",
729+
forkedFromParent: true,
730+
spawnDepth: 2,
731+
subagentRole: "orchestrator",
732+
subagentControlScope: "children",
733+
lastThreadId: 42,
734+
fastMode: true,
735+
verboseLevel: "on",
736+
updatedAt: 1_200,
737+
});
738+
739+
registerAgentRunContext("run-tool-owner", { sessionKey: "session-1", verboseLevel: "off" });
740+
toolEventRecipients.add("run-tool-owner", "conn-run");
741+
742+
handler({
743+
runId: "run-tool-owner",
744+
seq: 1,
745+
stream: "tool",
746+
ts: 1_234,
747+
data: {
748+
phase: "start",
749+
name: "exec",
750+
toolCallId: "tool-run-1",
751+
args: { command: "echo hi" },
752+
},
753+
});
754+
755+
expect(broadcastToConnIds).toHaveBeenCalledTimes(1);
756+
expect(broadcastToConnIds).toHaveBeenCalledWith(
757+
"agent",
758+
expect.objectContaining({
759+
runId: "run-tool-owner",
760+
sessionKey: "session-1",
761+
spawnedBy: "agent:main:main",
762+
spawnedWorkspaceDir: "/tmp/subagent",
763+
forkedFromParent: true,
764+
spawnDepth: 2,
765+
subagentRole: "orchestrator",
766+
subagentControlScope: "children",
767+
lastThreadId: 42,
768+
fastMode: true,
769+
verboseLevel: "on",
770+
stream: "tool",
771+
ts: 1_234,
772+
data: expect.objectContaining({
773+
phase: "start",
774+
name: "exec",
775+
toolCallId: "tool-run-1",
776+
args: { command: "echo hi" },
777+
}),
778+
}),
779+
new Set(["conn-run"]),
780+
);
781+
resetAgentRunContextForTest();
782+
});
783+
719784
it("broadcasts terminal session status to session subscribers on lifecycle end", () => {
720785
const { broadcastToConnIds, sessionEventSubscribers, handler } = createHarness({
721786
resolveSessionKeyForRun: () => "session-finished",

src/gateway/server-chat.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,11 @@ export function createAgentEventHandler({
770770
// messages to messaging surfaces (Telegram, Discord, etc.).
771771
const recipients = toolEventRecipients.get(evt.runId);
772772
if (recipients && recipients.size > 0) {
773-
broadcastToConnIds("agent", toolPayload, recipients);
773+
broadcastToConnIds(
774+
"agent",
775+
sessionKey ? { ...toolPayload, ...buildSessionEventSnapshot(sessionKey) } : toolPayload,
776+
recipients,
777+
);
774778
}
775779
// Session subscribers power operator UIs that attach to an existing
776780
// in-flight session after the run has already started. Those clients do

0 commit comments

Comments
 (0)