From 0cfe852c2d4f0893a7d77326995513916c79a872 Mon Sep 17 00:00:00 2001 From: imccyu <276526105+imccyu@users.noreply.github.com> Date: Sun, 9 Aug 2026 20:21:49 +0800 Subject: [PATCH] fix(ui-conversation): ignore legacy compact events without ids --- .../client/conversation-nodes/compaction.ts | 4 +++- .../conversation-node-definitions.spec.ts | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts b/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts index 04eace8038..d21b4aa4b4 100644 --- a/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts +++ b/packages/client/ui-conversation/src/client/conversation-nodes/compaction.ts @@ -39,7 +39,9 @@ export const compactionDefinition: ConversationNodeDefinition = || event.type === 'compact/summary' || event.type === 'compact/end') { if (event.data.sourceCommandId !== undefined) return null - return { id: String(event.data.compactionId), role: event.type === 'compact/start' ? 'start' : 'update' } + const compactionId: unknown = event.data.compactionId + if (typeof compactionId !== 'string' || compactionId === '') return null + return { id: compactionId, role: event.type === 'compact/start' ? 'start' : 'update' } } return null }, diff --git a/packages/client/ui-conversation/tests/conversation-node-definitions.spec.ts b/packages/client/ui-conversation/tests/conversation-node-definitions.spec.ts index d90093b864..016c7176db 100644 --- a/packages/client/ui-conversation/tests/conversation-node-definitions.spec.ts +++ b/packages/client/ui-conversation/tests/conversation-node-definitions.spec.ts @@ -698,6 +698,26 @@ describe('built-in conversation node Definitions', () => { }) }) + it('ignores legacy compaction transactions without correlation ids', () => { + const value = assembler([ + at(10, 'compact/start', { turn: null }), + at(11, 'compact/end', { turn: null, error: 'This operation was aborted' }), + at(20, 'compact/start', { turn: null }), + at(21, 'compact/summary', { + summary: [{ type: 'text', text: 'legacy summary' }], + shadowedSeqs: [1, 2, 3], + shadowedTokenCount: 42, + }), + at(22, 'user/message', { + ...textMessage('legacy-checkpoint', 'checkpoint'), + source: { kind: 'plugin', plugin: 'compact' }, + }, { surfaceOp: { op: 'replace', start: 1, end: 3 } }), + at(23, 'compact/end', { turn: null }), + ], true) + + expect(node(snapshot(value), 'compaction')).toBeUndefined() + }) + it('suppresses a turn error when the loaded tail contains only a later retry attempt', () => { const value = assembler([ at(5, 'llm/retry', {