fix(claude): preserve local command artifacts in session history

Claude writes slash-command metadata, local stdout, and compaction summaries
into the same JSONL stream as normal chat messages. The existing
normalization path treated those rows as internal content and dropped them
entirely.

That made the web UI diverge from the CLI transcript and removed important
context. Commands like /compact appeared to have never happened, the stdout
status line disappeared, and the continuation summary after compaction was
filtered out even though it best describes the post-boundary session state.

This change keeps the distinction between truly internal transcript rows and
user-visible local command artifacts. Command wrapper tags are parsed into
structured metadata without exposing the raw tags, local command stdout is
remapped to assistant text, and compact summaries are preserved as
assistant-authored content instead of being mislabeled as user input.

Search and session-summary parsing are updated for the same reason. If
history normalization preserved these rows but search still ignored them,
rendered conversation state and searchable conversation state would continue
to disagree, and session summaries would fall back to stale user text
instead of Claude's actual compaction summary.

The shared message and store typings are extended so this metadata survives
the full backend-to-frontend pipeline. That avoids reconstructing meaning
later and keeps the transcript faithful to Claude's persisted history while
still hiding genuinely internal control content.
This commit is contained in:
Haileyesus
2026-05-08 19:23:07 +03:00
parent 116f91bc3a
commit 17db71c43c
6 changed files with 347 additions and 22 deletions

View File

@@ -102,6 +102,21 @@ export type NormalizedMessage = {
kind: MessageKind;
role?: 'user' | 'assistant';
content?: string;
/**
* Optional display-oriented metadata used by providers that need to expose
* richer transcript artifacts without introducing a brand-new message kind.
*
* Current Claude usage:
* - local slash commands expose parsed command fields
* - compact summaries are flagged so the UI can treat them differently later
*/
displayText?: string;
commandName?: string;
commandMessage?: string;
commandArgs?: string;
isLocalCommand?: boolean;
isLocalCommandStdout?: boolean;
isCompactSummary?: boolean;
images?: unknown;
toolName?: string;
toolInput?: unknown;