fix(gateway): harden chat abort semantics

This commit is contained in:
Peter Steinberger
2026-01-10 17:23:16 +01:00
parent 84d64f9395
commit a1533a17f7
12 changed files with 456 additions and 111 deletions

View File

@@ -74,6 +74,7 @@ export type ChatRunState = {
registry: ChatRunRegistry;
buffers: Map<string, string>;
deltaSentAt: Map<string, number>;
abortedRuns: Map<string, number>;
clear: () => void;
};
@@ -81,17 +82,20 @@ export function createChatRunState(): ChatRunState {
const registry = createChatRunRegistry();
const buffers = new Map<string, string>();
const deltaSentAt = new Map<string, number>();
const abortedRuns = new Map<string, number>();
const clear = () => {
registry.clear();
buffers.clear();
deltaSentAt.clear();
abortedRuns.clear();
};
return {
registry,
buffers,
deltaSentAt,
abortedRuns,
clear,
};
}
@@ -212,6 +216,10 @@ export function createAgentEventHandler({
const chatLink = chatRunState.registry.peek(evt.runId);
const sessionKey =
chatLink?.sessionKey ?? resolveSessionKeyForRun(evt.runId);
const clientRunId = chatLink?.clientRunId ?? evt.runId;
const isAborted =
chatRunState.abortedRuns.has(clientRunId) ||
chatRunState.abortedRuns.has(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;
@@ -242,10 +250,16 @@ export function createAgentEventHandler({
if (sessionKey) {
bridgeSendToSession(sessionKey, "agent", agentPayload);
if (evt.stream === "assistant" && typeof evt.data?.text === "string") {
const clientRunId = chatLink?.clientRunId ?? evt.runId;
if (
!isAborted &&
evt.stream === "assistant" &&
typeof evt.data?.text === "string"
) {
emitChatDelta(sessionKey, clientRunId, evt.seq, evt.data.text);
} else if (lifecyclePhase === "end" || lifecyclePhase === "error") {
} else if (
!isAborted &&
(lifecyclePhase === "end" || lifecyclePhase === "error")
) {
if (chatLink) {
const finished = chatRunState.registry.shift(evt.runId);
if (!finished) {
@@ -268,6 +282,17 @@ export function createAgentEventHandler({
evt.data?.error,
);
}
} else if (
isAborted &&
(lifecyclePhase === "end" || lifecyclePhase === "error")
) {
chatRunState.abortedRuns.delete(clientRunId);
chatRunState.abortedRuns.delete(evt.runId);
chatRunState.buffers.delete(clientRunId);
chatRunState.deltaSentAt.delete(clientRunId);
if (chatLink) {
chatRunState.registry.remove(evt.runId, clientRunId, sessionKey);
}
}
}