From 217b7216485222c68d8fe82e4c9cc2708d30835c Mon Sep 17 00:00:00 2001 From: ekko <152005280+EKKOLearnAI@users.noreply.github.com> Date: Sat, 16 May 2026 11:15:29 +0800 Subject: [PATCH] clear stale compression status on run start (#783) --- packages/client/src/stores/hermes/chat.ts | 2 + tests/e2e/chat-streaming.spec.ts | 47 +++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/packages/client/src/stores/hermes/chat.ts b/packages/client/src/stores/hermes/chat.ts index 7415877..bc0cb18 100644 --- a/packages/client/src/stores/hermes/chat.ts +++ b/packages/client/src/stores/hermes/chat.ts @@ -953,6 +953,7 @@ export const useChatStore = defineStore('chat', () => { switch (evt.event) { case 'run.started': setAbortState(null) + setCompressionState(null) runProducedAssistantText = false runHadToolActivity = false closeStreamingAssistant() @@ -1419,6 +1420,7 @@ export const useChatStore = defineStore('chat', () => { case 'run.started': setAbortState(null) + setCompressionState(null) runProducedAssistantText = false runHadToolActivity = false closeStreamingAssistant() diff --git a/tests/e2e/chat-streaming.spec.ts b/tests/e2e/chat-streaming.spec.ts index ffa87f9..3ee3b79 100644 --- a/tests/e2e/chat-streaming.spec.ts +++ b/tests/e2e/chat-streaming.spec.ts @@ -171,6 +171,53 @@ test('keeps queued runs on one socket and does not duplicate streamed handlers', expect(api.unexpectedRequests).toEqual([]) }) +test('clears previous compression status when a new run starts', async ({ page }) => { + await authenticate(page, TEST_ACCESS_KEY, 'research') + const api = await mockHermesApi(page) + await mockChatSocket(page) + + await page.goto('/#/hermes/chat') + + await sendChatMessage(page, 'Trigger compression before answering') + const first = await waitForRun(page) + + await page.evaluate((sid) => { + const socket = (window as any).__PW_CHAT_SOCKET__.latest + socket.__trigger('run.started', { event: 'run.started', session_id: sid, run_id: 'run-1' }) + socket.__trigger('compression.completed', { + event: 'compression.completed', + session_id: sid, + totalMessages: 12, + beforeTokens: 24000, + afterTokens: 6000, + compressed: true, + }) + }, first.run.session_id) + + await expect(page.getByText(/Compressed 12 msgs/)).toBeVisible() + + await page.evaluate((sid) => { + const socket = (window as any).__PW_CHAT_SOCKET__.latest + socket.__trigger('run.completed', { + event: 'run.completed', + session_id: sid, + run_id: 'run-1', + output: 'First answer', + }) + }, first.run.session_id) + + await sendChatMessage(page, 'Start another turn') + const second = await waitForRun(page, 1) + + await page.evaluate((sid) => { + const socket = (window as any).__PW_CHAT_SOCKET__.latest + socket.__trigger('run.started', { event: 'run.started', session_id: sid, run_id: 'run-2' }) + }, second.run.session_id) + + await expect(page.getByText(/Compressed 12 msgs/)).toHaveCount(0) + expect(api.unexpectedRequests).toEqual([]) +}) + test('surfaces an empty completed run as an error instead of leaving chat stalled', async ({ page }) => { await authenticate(page, TEST_ACCESS_KEY, 'research') const api = await mockHermesApi(page)