Skip to content

Conversation

@fkesheh
Copy link
Contributor

@fkesheh fkesheh commented Feb 6, 2026

Summary

  • Preserve active tasks across conversation summarization by including the current todo list alongside the context summary
  • buildSummaryMessage now accepts an optional Todo[] and appends a <current_todos> XML block when todos are non-empty
  • checkAndSummarizeIfNeeded passes todos through from the call site in chat-handler.ts via getTodoManager().getAllTodos()

Test plan

  • npx tsc --noEmit --skipLibCheck passes
  • All 10 summarization tests pass (8 existing + 2 new)
  • 100% line coverage on summarization module
  • New test: verifies <current_todos> block with formatted todo lines when todos exist
  • New test: verifies no <current_todos> block when todos are empty

Summary by CodeRabbit

  • New Features

    • Summaries now include a formatted todo section, retain recent messages for continuity, and support incremental/first-time condensation with improved prompts and token-threshold handling.
    • Summarization can be cancelled via abort signals.
  • Bug Fixes

    • Summary invalidation is more selective and time-aware; persistence and save failures no longer block UI flow.
    • Message re-truncation ensures token budgets are respected after inserting summaries.
  • Tests

    • Added comprehensive unit tests covering summarization, todos, aborts, persistence, and edge cases.

…odule

Split monolithic file into focused modules:
- constants.ts: configuration values
- prompts.ts: AI summarization prompts
- helpers.ts: utility functions
- index.ts: main checkAndSummarizeIfNeeded export

Added integration tests following testing trophy philosophy.
Move token threshold check, message splitting, summary generation,
message building, and persistence into helpers.ts. Remove dead
re-exports and unreachable guard. 100% test coverage.
Preserve active tasks across conversation summarization by appending
the current todo list as a <current_todos> XML block alongside the
<context_summary> in the summary message.
@vercel
Copy link

vercel bot commented Feb 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hackerai Ready Ready Preview, Comment Feb 10, 2026 8:50pm

Request Review

@coderabbitai
Copy link

coderabbitai bot commented Feb 6, 2026

📝 Walkthrough

Walkthrough

Refactors chat summarization into a new lib/chat/summarization module (constants, prompts, helpers, index), removes lib/utils/message-summarization.ts, adds extensive unit tests, updates lib/api/chat-handler.ts to import the new module and pass current todos plus an abort signal, adjusts DB truncation after summaries, and changes summary invalidation in convex/messages.ts.

Changes

Cohort / File(s) Summary
Summarization Core
lib/chat/summarization/index.ts, lib/chat/summarization/helpers.ts, lib/chat/summarization/constants.ts, lib/chat/summarization/prompts.ts
New modular summarization implementation: token-threshold logic, message splitting, prompt variants, summary generation (incremental + fallback), building a <context_summary> UI message (optional <current_todos>), persistence, and exported checkAndSummarizeIfNeeded + SummarizationResult.
Tests
lib/chat/summarization/__tests__/index.test.ts
Adds comprehensive unit tests covering gating, token thresholds, agent vs ask prompts, incremental/first-time summarization, todos inclusion, abort handling, persistence success/failure, and utilities (isSummaryMessage/extractSummaryText).
Call Site Update
lib/api/chat-handler.ts
Updated import path to @/lib/chat/summarization and extended two calls to checkAndSummarizeIfNeeded to pass getTodoManager().getAllTodos() and userStopSignal.signal (todos and abort signal).
DB message handling
lib/db/actions.ts
After injecting a summary message, re-truncates subsequent messages to fit remaining token budget using truncateMessagesToTokenLimit, returning summary + re-truncated messages.
Removed Legacy
lib/utils/message-summarization.ts
Deleted legacy monolithic summarization implementation (responsibilities migrated to new module).
Related Chat Invalidation
convex/messages.ts
Reworked summary invalidation to use creation-time comparison against cutoff message, perform guarded invalidation only when appropriate, and integrate checks before deletions/regeneration with best-effort error handling.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant ChatHandler as Chat Handler
  participant TodoMgr as Todo Manager
  participant Summarizer as Summarization Module
  participant LM as Language Model
  participant DB as Database
  participant Writer as UI Writer

  Client->>ChatHandler: new message / step
  ChatHandler->>TodoMgr: getAllTodos()
  ChatHandler->>Summarizer: checkAndSummarizeIfNeeded(uiMessages, sub, LM, mode, Writer, chatId, fileTokens, todos, abortSignal)
  Summarizer->>Writer: signal summarization start
  Summarizer->>LM: generate summary (prompt + messages, abortable)
  LM-->>Summarizer: summary text / error
  Summarizer->>DB: persist summary (chatId, cutoffMessageId)
  DB-->>Summarizer: persist result / error
  Summarizer->>Writer: signal summarization complete (summary or fallback)
  Summarizer-->>ChatHandler: SummarizationResult
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰✨ A rabbit hops through code with glee,

I tuck old files and craft a key,
Todos snug in context wrapped,
Summaries trimmed, no thread unzapped,
Tests all dance — hooray for me! 🥕🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: include todo list in summarization output' accurately describes the main feature addition—integrating todo lists into the summarization process, which aligns with the PR objectives of preserving active tasks across conversation summarization.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor-chat-sumarization

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@lib/chat/summarization/helpers.ts`:
- Around line 90-108: The buildSummaryMessage function currently interpolates
summaryText and each todo.content directly into XML-like tags; to prevent
tag-breaking when content contains XML-like strings, HTML-escape special
characters (at least &, <, >, " and ') before interpolation. Add or use a helper
like escapeXml and apply it to summaryText and todo.content (used in the
todos.map) so the generated <context_summary> and <current_todos> blocks remain
well-formed; keep the rest of buildSummaryMessage (id, role, parts) unchanged.
🧹 Nitpick comments (1)
lib/chat/summarization/__tests__/index.test.ts (1)

304-328: LGTM — correctly validates absence of todo block for empty array.

Minor style note: this test uses a type assertion on Line 323–324 (as { type: string; text: string }) while the preceding test (Line 281) accesses the same property without one. Harmless but slightly inconsistent.

…rized content

Previously, deleteLastAssistantMessage and regenerateWithNewContent
unconditionally nuked the summary on every delete/edit. The existing
checkAndInvalidateSummary helper was never called (dead code) and also
had a bug comparing by exact message ID — which fails when the cutoff
is a user message but we're deleting an assistant message.

Now both mutations call checkAndInvalidateSummary before deleting,
comparing by creation time to correctly detect overlap regardless of
message role.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The summarization LLM call was not receiving the abort signal, so when
a user clicked "Stop" the generateText call would continue to completion,
wasting tokens and ignoring timeouts. Now the signal propagates through
checkAndSummarizeIfNeeded → generateSummaryText → generateText, and
abort errors skip persist/completion instead of falling back silently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y degradation

- Separate synthetic summary messages from real messages before splitting
  so cutoff ID always references a DB message (Bug 1)
- Use incremental summarization with previous_summary context instead of
  summarizing-a-summary (Bug 2)
- Add try-catch around summary deletion in !cutoffMessage branch (Bug 3)
- Re-truncate after summary injection reserving summary token budget first
  to prevent exceeding token limits (Bug 4)
- Add isSummaryMessage and extractSummaryText helpers
- Add 6 new test cases covering re-summarization scenarios
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.

2 participants