Fix streaming double-dispatch: suppress raw chunks during provisional buffering

This commit is contained in:
Mohamed Boudra
2026-03-25 20:39:08 +07:00
parent c2d8cbdb2e
commit ce8128910e
2 changed files with 5 additions and 11 deletions
@@ -1384,7 +1384,7 @@ describe("AgentManager", () => {
expect(fetched.rows.map((row) => row.seq)).toEqual([1, 2]);
});
test("streams assistant chunks provisionally and commits one finalized assistant row", async () => {
test("buffers assistant chunks provisionally and streams one finalized assistant row", async () => {
const workdir = mkdtempSync(join(tmpdir(), "agent-manager-provisional-timeline-"));
const storagePath = join(workdir, "agents");
const storage = new AgentStorage(storagePath, logger);
@@ -1435,18 +1435,10 @@ describe("AgentManager", () => {
}
const assistantTimelineEvents = streamEvents.filter((event) => event.itemType === "assistant_message");
expect(assistantTimelineEvents).toHaveLength(3);
expect(assistantTimelineEvents).toHaveLength(1);
expect(assistantTimelineEvents[0]).toMatchObject({
eventType: "timeline",
itemType: "assistant_message",
text: "final ",
});
expect(assistantTimelineEvents[0]?.seq).toBeUndefined();
expect(assistantTimelineEvents[1]).toMatchObject({
text: "reply",
});
expect(assistantTimelineEvents[1]?.seq).toBeUndefined();
expect(assistantTimelineEvents[2]).toMatchObject({
text: "final reply",
seq: 1,
});
@@ -1972,6 +1972,7 @@ export class AgentManager {
const isForegroundEvent = Boolean(
eventTurnId && agent.activeForegroundTurnId === eventTurnId,
);
let suppressLiveDispatch = false;
// Only update timestamp for live events, not history replay
if (!options?.fromHistory) {
@@ -2027,6 +2028,7 @@ export class AgentManager {
}
if (event.item.type === "assistant_message") {
agent.provisionalAssistantText = `${agent.provisionalAssistantText ?? ""}${event.item.text}`;
suppressLiveDispatch = true;
break;
}
if (event.item.type === "reasoning") {
@@ -2194,7 +2196,7 @@ export class AgentManager {
}
// Skip dispatching individual stream events during history replay.
if (!options?.fromHistory) {
if (!options?.fromHistory && !suppressLiveDispatch) {
this.dispatchStream(
agent.id,
event,