From 7a8f1c3e87a8ca957bb368ddd013b4a55d0934cf Mon Sep 17 00:00:00 2001 From: weishu Date: Tue, 27 Jan 2026 10:03:09 +0800 Subject: [PATCH] feat: add compact_boundary event support in web UI https://github.com/tiann/hapi/issues/108#issuecomment-3799439152 --- web/src/chat/normalizeAgent.ts | 16 ++++++++++++++++ web/src/chat/presentation.ts | 3 +++ web/src/chat/types.ts | 1 + 3 files changed, 20 insertions(+) diff --git a/web/src/chat/normalizeAgent.ts b/web/src/chat/normalizeAgent.ts index a16f4678..ec5c6575 100644 --- a/web/src/chat/normalizeAgent.ts +++ b/web/src/chat/normalizeAgent.ts @@ -263,6 +263,22 @@ export function normalizeAgentRecord( meta } } + if (data.type === 'system' && data.subtype === 'compact_boundary') { + const metadata = isObject(data.compactMetadata) ? data.compactMetadata : null + return { + id: messageId, + localId, + createdAt, + role: 'event', + content: { + type: 'compact', + trigger: asString(metadata?.trigger) ?? 'auto', + preTokens: asNumber(metadata?.preTokens) ?? 0 + }, + isSidechain: false, + meta + } + } return null } diff --git a/web/src/chat/presentation.ts b/web/src/chat/presentation.ts index 67a0f6ad..e1d45320 100644 --- a/web/src/chat/presentation.ts +++ b/web/src/chat/presentation.ts @@ -63,6 +63,9 @@ export function getEventPresentation(event: AgentEvent): EventPresentation { const formatted = saved >= 1000 ? `${Math.round(saved / 1000)}K` : String(saved) return { icon: '📦', text: `Context compacted (saved ${formatted} tokens)` } } + if (event.type === 'compact') { + return { icon: '📦', text: 'Conversation compacted' } + } try { return { icon: null, text: JSON.stringify(event) } } catch { diff --git a/web/src/chat/types.ts b/web/src/chat/types.ts index 4a60ee53..fbaa5b41 100644 --- a/web/src/chat/types.ts +++ b/web/src/chat/types.ts @@ -17,6 +17,7 @@ export type AgentEvent = | { type: 'api-error'; retryAttempt: number; maxRetries: number; error: unknown } | { type: 'turn-duration'; durationMs: number } | { type: 'microcompact'; trigger: string; preTokens: number; tokensSaved: number } + | { type: 'compact'; trigger: string; preTokens: number } | ({ type: string } & Record) export type ToolResultPermission = {