fix(ui): avoid session list reloads for chat turns

This commit is contained in:
VACInc
2026-05-03 08:34:03 -04:00
committed by Peter Steinberger
parent 9e56cfcc35
commit a0e526c163
2 changed files with 49 additions and 17 deletions

View File

@@ -150,7 +150,7 @@ describe("handleGatewayEvent sessions.changed", () => {
expect(loadSessionsMock).not.toHaveBeenCalled();
});
it("reloads sessions when an applied message-phase event inserts a session row", () => {
it("does not reload sessions when a message-phase event inserts a session row", () => {
loadSessionsMock.mockReset();
applySessionsChangedEventMock
.mockReset()
@@ -170,11 +170,10 @@ describe("handleGatewayEvent sessions.changed", () => {
});
expect(applySessionsChangedEventMock).toHaveBeenCalledTimes(1);
expect(loadSessionsMock).toHaveBeenCalledTimes(1);
expect(loadSessionsMock).toHaveBeenCalledWith(host);
expect(loadSessionsMock).not.toHaveBeenCalled();
});
it("reloads sessions when a message-phase event cannot patch local state", () => {
it("does not reload sessions when a message-phase event cannot patch local state", () => {
loadSessionsMock.mockReset();
applySessionsChangedEventMock.mockReset().mockReturnValue({ applied: false });
const host = createHost();
@@ -186,8 +185,39 @@ describe("handleGatewayEvent sessions.changed", () => {
seq: 1,
});
expect(loadSessionsMock).toHaveBeenCalledTimes(1);
expect(loadSessionsMock).toHaveBeenCalledWith(host);
expect(loadSessionsMock).not.toHaveBeenCalled();
});
it("does not reload sessions for chat lifecycle events", () => {
loadSessionsMock.mockReset();
applySessionsChangedEventMock.mockReset().mockReturnValue({ applied: true, change: "updated" });
const host = createHost();
handleGatewayEvent(host, {
type: "event",
event: "sessions.changed",
payload: { sessionKey: "agent:main:main", phase: "start", runId: "run-1" },
seq: 1,
});
expect(applySessionsChangedEventMock).toHaveBeenCalledTimes(1);
expect(loadSessionsMock).not.toHaveBeenCalled();
});
it("does not reload sessions for chat send acknowledgement events", () => {
loadSessionsMock.mockReset();
applySessionsChangedEventMock.mockReset().mockReturnValue({ applied: true, change: "updated" });
const host = createHost();
handleGatewayEvent(host, {
type: "event",
event: "sessions.changed",
payload: { sessionKey: "agent:main:main", reason: "send" },
seq: 1,
});
expect(applySessionsChangedEventMock).toHaveBeenCalledTimes(1);
expect(loadSessionsMock).not.toHaveBeenCalled();
});
});

View File

@@ -156,12 +156,18 @@ function isTerminalChatState(
return state === "final" || state === "aborted" || state === "error";
}
function isSessionMessagePhasePayload(payload: unknown): boolean {
function isChatTurnSessionChangedPayload(payload: unknown): boolean {
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
return false;
}
const record = payload as { phase?: unknown; reason?: unknown };
return (
Boolean(payload) &&
typeof payload === "object" &&
!Array.isArray(payload) &&
(payload as { phase?: unknown }).phase === "message"
record.phase === "start" ||
record.phase === "message" ||
record.phase === "end" ||
record.phase === "error" ||
record.reason === "send" ||
record.reason === "steer"
);
}
@@ -749,12 +755,8 @@ function handleGatewayEventUnsafe(host: GatewayHost, evt: GatewayEventFrame) {
}
if (evt.event === "sessions.changed") {
const applyResult = applySessionsChangedEvent(host as unknown as SessionsState, evt.payload);
if (
applyResult.applied &&
applyResult.change === "updated" &&
isSessionMessagePhasePayload(evt.payload)
) {
applySessionsChangedEvent(host as unknown as SessionsState, evt.payload);
if (isChatTurnSessionChangedPayload(evt.payload)) {
return;
}
void loadSessions(host as unknown as SessionsState);