fix: stream tool summaries early and tool output

This commit is contained in:
Peter Steinberger
2026-01-03 20:37:57 +01:00
parent 03c1599544
commit a15cffb7de
15 changed files with 379 additions and 122 deletions

View File

@@ -186,12 +186,18 @@ export function createAgentEventHandler({
};
return (evt: AgentEventPayload) => {
const chatLink = chatRunState.registry.peek(evt.runId);
const sessionKey =
chatLink?.sessionKey ?? resolveSessionKeyForRun(evt.runId);
// Include sessionKey so Control UI can filter tool streams per session.
const agentPayload = sessionKey ? { ...evt, sessionKey } : evt;
const last = agentRunSeq.get(evt.runId) ?? 0;
if (evt.seq !== last + 1) {
broadcast("agent", {
runId: evt.runId,
stream: "error",
ts: Date.now(),
sessionKey,
data: {
reason: "seq gap",
expected: last + 1,
@@ -200,18 +206,15 @@ export function createAgentEventHandler({
});
}
agentRunSeq.set(evt.runId, evt.seq);
broadcast("agent", evt);
broadcast("agent", agentPayload);
const chatLink = chatRunState.registry.peek(evt.runId);
const sessionKey =
chatLink?.sessionKey ?? resolveSessionKeyForRun(evt.runId);
const jobState =
evt.stream === "job" && typeof evt.data?.state === "string"
? (evt.data.state as "done" | "error" | string)
: null;
if (sessionKey) {
bridgeSendToSession(sessionKey, "agent", evt);
bridgeSendToSession(sessionKey, "agent", agentPayload);
if (evt.stream === "assistant" && typeof evt.data?.text === "string") {
const clientRunId = chatLink?.clientRunId ?? evt.runId;
emitChatDelta(sessionKey, clientRunId, evt.seq, evt.data.text);

View File

@@ -478,4 +478,43 @@ describe("gateway server agent", () => {
ws.close();
await server.close();
});
test("agent events include sessionKey in agent payloads", async () => {
const { server, ws } = await startServerWithClient();
await connectOk(ws, {
client: {
name: "webchat",
version: "1.0.0",
platform: "test",
mode: "webchat",
},
});
registerAgentRunContext("run-tool-1", { sessionKey: "main" });
const agentEvtP = onceMessage(
ws,
(o) =>
o.type === "event" &&
o.event === "agent" &&
o.payload?.runId === "run-tool-1",
8000,
);
emitAgentEvent({
runId: "run-tool-1",
stream: "tool",
data: { phase: "start", name: "read", toolCallId: "tool-1" },
});
const evt = await agentEvtP;
const payload =
evt.payload && typeof evt.payload === "object"
? (evt.payload as Record<string, unknown>)
: {};
expect(payload.sessionKey).toBe("main");
ws.close();
await server.close();
});
});