Skip to content

fix(chat): preserve messages after summarization#3280

Merged
WillemJiang merged 4 commits into
bytedance:mainfrom
ggnnggez:fix-2965
May 29, 2026
Merged

fix(chat): preserve messages after summarization#3280
WillemJiang merged 4 commits into
bytedance:mainfrom
ggnnggez:fix-2965

Conversation

@ggnnggez
Copy link
Copy Markdown
Collaborator

@ggnnggez ggnnggez commented May 27, 2026

Summary

Fixed #2965

  • Preserve visible chat history when summarization resets the live message stream.
  • Match DeerFlow summarization update keys by the stable SummarizationMiddleware.before_model suffix instead of one exact class name.
  • Add frontend coverage for hidden control-message dedupe and DeerFlow summarization update keys.
  • Add a backend regression guard for the frontend/backend summarization update-key contract.

Root Cause

The backend emits summarization updates under DeerFlowSummarizationMiddleware.before_model, while the frontend only listened for SummarizationMiddleware.before_model. As a result, the frontend missed the summarization reset update and did not move visible messages into local history before RemoveMessage(remove_all) cleared the live stream.

Validation

pnpm test tests/unit/core/threads/message-merge.test.ts
pnpm lint
uv run pytest tests/test_lead_agent_model_resolution.py -k summarization_middleware_preserves_frontend_update_key_contract
uv run pytest tests/test_lead_agent_model_resolution.py -k "create_summarization_middleware"
commit hook: frontend check and backend lint passed

Note: pnpm typecheck was previously blocked by stale Next generated route types under .next/types versus .next/dev/types, unrelated to this change.

@ggnnggez ggnnggez requested a review from WillemJiang May 27, 2026 10:10
@ggnnggez ggnnggez marked this pull request as ready for review May 27, 2026 10:12
@WillemJiang WillemJiang requested a review from Copilot May 27, 2026 10:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a frontend/backend contract mismatch that caused chat history to disappear from the active “new conversation” view after summarization-triggered stream resets, by broadening the frontend’s summarization update-key matching and improving message deduplication around hidden control messages.

Changes:

  • Frontend: preserve visible history across summarization resets by matching any *.SummarizationMiddleware.before_model update key and moving pre-reset messages into history before the live stream clears.
  • Frontend: adjust message deduplication/overlap logic to ensure hidden control messages don’t evict visible messages with the same identity.
  • Tests: add frontend unit coverage for hidden-message dedupe + update-key matching; add backend regression test to guard the update-key suffix contract.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
frontend/src/core/threads/hooks.ts Matches summarization updates by stable suffix, preserves visible messages on reset, and avoids hidden-message dedupe issues.
frontend/tests/unit/core/threads/message-merge.test.ts Adds unit tests for hidden-message ID reuse and DeerFlow summarization update-key matching.
backend/tests/test_lead_agent_model_resolution.py Adds regression guard ensuring summarization middleware class name keeps the SummarizationMiddleware.before_model suffix.

@WillemJiang
Copy link
Copy Markdown
Collaborator

@ggnnggez Here are some review comments.

  1. Loose key matching in getSummarizationMiddlewareMessages — endsWith("SummarizationMiddleware.before_model") could theoretically match a future unrelated key that happens to share the suffix. Consider adding a more specific check (e.g., key === "SummarizationMiddleware.before_model" || key === "DeerFlowSummarizationMiddleware.before_model") or at least a comment documenting the known keys. The current approach is fine for now given it's unlikely, but it's fragile against accidental matches.
  2. mergeMessages filtering hidden messages from overlap — The change at line ~113 filters hidden messages out of threadMessages when building the overlap set. This is correct for the summarization case, but it is worth verifying that there are no other call sites where hidden messages in thread messages are meaningful for overlap detection.
  3. Backend test is a naming contract, not a behavior test — The backend test only checks type(middleware).name ends with SummarizationMiddleware. It doesn't verify that the middleware actually emits the right update keys at runtime. If someone renames the class, this test passes but the contract breaks silently. The PR description acknowledges this ("Remove this test once the frontend and backend have a stronger explicit contract"), which is fair.

@WillemJiang WillemJiang added the reviewing The PR is in reviewing status label May 28, 2026
@ggnnggez
Copy link
Copy Markdown
Collaborator Author

ggnnggez commented May 28, 2026

Thanks for the review. Addressed in e584efd

  1. Replaced suffix matching with an explicit allowlist for SummarizationMiddleware.before_model and DeerFlowSummarizationMiddleware.before_model, plus a negative test for suffix-sharing keys.
  2. Verified mergeMessages has a single production call site in the UI stream merge path. Added coverage around hidden/visible overlap and comments clarifying that hidden messages in this path are UI control messages, not task/tracing records.
  3. Added a runtime create_agent(...).stream(stream_mode="updates") regression test that asserts the actual DeerFlowSummarizationMiddleware.before_model update key and summary reset payload are emitted.

@WillemJiang WillemJiang merged commit d46a577 into bytedance:main May 29, 2026
7 checks passed
jtaynl added a commit to jtaynl/deer-flow that referenced this pull request May 29, 2026
- d46a577 fix(chat): preserve messages after summarization (bytedance#3280)
  Directly relevant to this deployment since we run summarization with
  the raised 32K trigger (tuning recommendation, 2026-05-23). Prior bug
  could silently drop post-summary messages from chat history during
  long research threads.

No conflicts on overlap-risk paths. No new gotchas — fix is transparent.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ggnnggez ggnnggez removed the reviewing The PR is in reviewing status label May 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

新对话页发生上下文压缩后继续聊天,顶部无法继续加载更早历史消息

3 participants