From 55b39563a0ba746438f6b80d24287dc88ae68aa6 Mon Sep 17 00:00:00 2001 From: steven_li Date: Tue, 26 May 2026 13:49:31 +0800 Subject: [PATCH] test: cover task detail live timeline updates --- app-instance/frontend/lib/store.test.ts | 25 +++++++++++++++++++++++++ app-instance/frontend/lib/store.ts | 11 ++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/app-instance/frontend/lib/store.test.ts b/app-instance/frontend/lib/store.test.ts index 0a8aab1..9f32f81 100644 --- a/app-instance/frontend/lib/store.test.ts +++ b/app-instance/frontend/lib/store.test.ts @@ -64,4 +64,29 @@ describe('chat store process event ingestion', () => { expect(useChatStore.getState().getInputDraft('web:alpha')).toBe(''); expect(useChatStore.getState().getInputDraft('web:beta')).toBe('message for beta'); }); + + it('keeps live task events after persisted session projection is merged', () => { + const store = useChatStore.getState(); + store.setSessionId('web:default'); + store.ingestProcessEvent({ + type: 'process_run_progress', + session_id: 'web:default', + run_id: 'run-live', + parent_run_id: null, + actor_type: 'agent', + actor_id: 'main-agent', + actor_name: 'Main Agent', + text: '正在调用工具', + metadata: { task_id: 'task-live', timeline_type: 'tool_call' }, + created_at: '2026-05-26T10:00:00.000Z', + }); + + store.setSessionProcess('web:default', { + runs: [], + events: [], + artifacts: [], + }); + + expect(useChatStore.getState().processEvents.some((event) => event.run_id === 'run-live')).toBe(true); + }); }); diff --git a/app-instance/frontend/lib/store.ts b/app-instance/frontend/lib/store.ts index d6c616f..c04e45a 100644 --- a/app-instance/frontend/lib/store.ts +++ b/app-instance/frontend/lib/store.ts @@ -117,6 +117,11 @@ function appendEvent(collection: ProcessEvent[], event: ProcessEvent): ProcessEv return [...collection, event]; } +function hasTaskMetadata(item: { metadata?: Record }): boolean { + const taskId = item.metadata?.task_id; + return typeof taskId === 'string' && taskId.trim().length > 0; +} + function createEventId(event: ProcessWsEvent): string { if (event.type === 'process_cancel_ack') { return `${event.type}:${event.run_id}`; @@ -393,7 +398,11 @@ export const useChatStore = create((set, get) => ({ const incomingArtifacts = projection.artifacts || []; const incomingRunIds = new Set(incomingRuns.map((run) => run.run_id)); const nextRuns = [ - ...state.processRuns.filter((run) => run.session_id !== sessionId && !incomingRunIds.has(run.run_id)), + ...state.processRuns.filter((run) => { + if (incomingRunIds.has(run.run_id)) return false; + if (run.session_id !== sessionId) return true; + return hasTaskMetadata(run); + }), ...incomingRuns, ]; const liveRunIds = new Set(nextRuns.map((run) => run.run_id));