perf(webchat): skip unnecessary full history reloads on final events (#20588)
Co-authored-by: amzzzzzzz <154392693+amzzzzzzz@users.noreply.github.com>
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
} from "./app-settings.ts";
|
||||
import { handleAgentEvent, resetToolStream, type AgentEventPayload } from "./app-tool-stream.ts";
|
||||
import type { OpenClawApp } from "./app.ts";
|
||||
import { shouldReloadHistoryForFinalEvent } from "./chat-event-reload.ts";
|
||||
import { loadAgents } from "./controllers/agents.ts";
|
||||
import { loadAssistantIdentity } from "./controllers/assistant-identity.ts";
|
||||
import { loadChatHistory } from "./controllers/chat.ts";
|
||||
@@ -256,7 +257,7 @@ function handleGatewayEventUnsafe(host: GatewayHost, evt: GatewayEventFrame) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state === "final") {
|
||||
if (state === "final" && shouldReloadHistoryForFinalEvent(payload)) {
|
||||
void loadChatHistory(host as unknown as OpenClawApp);
|
||||
}
|
||||
return;
|
||||
|
||||
47
ui/src/ui/chat-event-reload.test.ts
Normal file
47
ui/src/ui/chat-event-reload.test.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { shouldReloadHistoryForFinalEvent } from "./chat-event-reload.ts";
|
||||
|
||||
describe("shouldReloadHistoryForFinalEvent", () => {
|
||||
it("returns false for non-final events", () => {
|
||||
expect(
|
||||
shouldReloadHistoryForFinalEvent({
|
||||
runId: "run-1",
|
||||
sessionKey: "main",
|
||||
state: "delta",
|
||||
message: { role: "assistant", content: [{ type: "text", text: "x" }] },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true when final event has no message payload", () => {
|
||||
expect(
|
||||
shouldReloadHistoryForFinalEvent({
|
||||
runId: "run-1",
|
||||
sessionKey: "main",
|
||||
state: "final",
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when final event includes assistant payload", () => {
|
||||
expect(
|
||||
shouldReloadHistoryForFinalEvent({
|
||||
runId: "run-1",
|
||||
sessionKey: "main",
|
||||
state: "final",
|
||||
message: { role: "assistant", content: [{ type: "text", text: "done" }] },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true when final event message role is non-assistant", () => {
|
||||
expect(
|
||||
shouldReloadHistoryForFinalEvent({
|
||||
runId: "run-1",
|
||||
sessionKey: "main",
|
||||
state: "final",
|
||||
message: { role: "user", content: [{ type: "text", text: "echo" }] },
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
16
ui/src/ui/chat-event-reload.ts
Normal file
16
ui/src/ui/chat-event-reload.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { ChatEventPayload } from "./controllers/chat.ts";
|
||||
|
||||
export function shouldReloadHistoryForFinalEvent(payload?: ChatEventPayload): boolean {
|
||||
if (!payload || payload.state !== "final") {
|
||||
return false;
|
||||
}
|
||||
if (!payload.message || typeof payload.message !== "object") {
|
||||
return true;
|
||||
}
|
||||
const message = payload.message as Record<string, unknown>;
|
||||
const role = typeof message.role === "string" ? message.role.toLowerCase() : "";
|
||||
if (role && role !== "assistant") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user