Skip to content

feat(threads): add title summary generation and settings - #1256

Closed
maria-rcks wants to merge 5 commits into
pingdotgg:mainfrom
maria-rcks:feat/title-summaries
Closed

maria-rcks wants to merge 5 commits into
pingdotgg:mainfrom
maria-rcks:feat/title-summaries

Conversation

@maria-rcks

@maria-rcks maria-rcks commented Mar 20, 2026 •

Copy link
Copy Markdown
Collaborator

What Changed

This PR adds title summaries for threads.

Titles are generated based on the first prompt, there is a manual "Generate title summary" action in the thread menu. I also added an option to fchoose which model is being used for this task.

Why

This is better because it makes threads easier to organize and recognize at a glance. When titles reflect what the thread is actually about, it is easier to scan a long list of threads and come back to older work later.

UI Changes

Added thread title summary controls in Settings > Threads and a manual title summary action in the thread context menu.

image

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

closes #990

Note

Add automatic thread title generation via Codex with settings controls

  • Adds a generateThreadTitle WebSocket method on the server that prompts Codex with recent user messages and attachments, sanitizes the output to a max-60-char single-line title, and returns it to the client.
  • Introduces titleSummaryState ("missing", "generated", "manual") on threads throughout the stack: contracts, orchestration events, projections, DB migration, and local state.
  • Replaces the previous immediate first-message title update in ChatView with an async call to generateAndRenameThreadTitle, gated by the new titleSummaryMode: 'automatic' app setting.
  • Adds settings UI controls for enabling/disabling automatic title summaries and selecting the model used for generation.
  • Adds DB migration 016 for title_summary_state column and migration 017 to normalize legacy piAgent provider names to codex across persisted rows and event JSON.
  • Behavioral Change: manual renames in the sidebar now set titleSummaryState to "manual"; first-message titling is no longer synchronous and will surface a toast error on failure.

Macroscope summarized 5e0a014.


Note

Medium Risk
Adds new persisted thread metadata (titleSummaryState) plus DB migrations and replay-time normalization of legacy provider values, which can affect read models and event replay if incorrect, but changes are localized and covered by tests.

Overview
Adds end-to-end thread title summary generation: a new server.generateThreadTitle WebSocket method gathers recent user messages/attachments and calls the Codex text generation service to produce a sanitized <=60 char title.

Introduces and persists titleSummaryState (missing | generated | manual) across thread create/meta-update commands, events, projectors, snapshot queries, and the projection_threads table (new migration).

Updates the web app to optionally auto-generate a title after the first message (setting titleSummaryMode) and to allow manual generation from the thread context menu; manual renames now mark the state as manual, and a separate titleSummaryModel setting controls which model is used.

Adds compatibility for legacy piAgent provider identifiers by normalizing them to codex during event-store replay and provider-session reads (plus a data migration), and hardens terminal state persistence to fall back to in-memory storage when localStorage isn’t available.

Written by Cursor Bugbot for commit 5e0a014. This will update automatically on new commits. Configure here.

@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Mar 20, 2026
@coderabbitai

coderabbitai Bot commented Mar 20, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1acf233a-238a-4432-8384-b44009274415

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@binbandit

Copy link
Copy Markdown
Contributor

Great work, id propose that we occasionally re-trigger to update the title?
Such as if a pull request opens for the work etc

@maria-rcks

Copy link
Copy Markdown
Collaborator Author

Great work, id propose that we occasionally re-trigger to update the title? Such as if a pull request opens for the work etc

I thought about this but how do we measure when to re-trigger?
Like every ten prompts or when things are committed, or what is the threshold?

Would love Julius comments on this.

@maria-rcks

Copy link
Copy Markdown
Collaborator Author

also could be a separate pr

@binbandit

Copy link
Copy Markdown
Contributor

Happy for it to be a separate PR

@maria-rcks
maria-rcks force-pushed the feat/title-summaries branch from 267b38f to 1b77529 Compare March 24, 2026 13:20
@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:XL 500-999 changed lines (additions + deletions). labels Mar 24, 2026
description: error instanceof Error ? error.message : "An error occurred.",
});
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Title generation reads messages before projection stores them

High Severity

maybeGenerateFirstThreadTitle fires immediately after the thread.turn.start dispatch succeeds. The server-side generateThreadTitle reads user messages from the projection snapshot. However, thread.turn.start only produces a thread.turn-start-requested event — the actual thread.message-sent event that populates thread.messages in the projection is emitted later by ProviderRuntimeIngestion asynchronously. So the snapshot will contain zero user messages, causing the function to always fail with "Thread has no user messages to summarize" and show an error toast to the user.

Additional Locations (1)
Fix in Cursor Fix in Web

commandId: providerCommandId(event, "thread-meta-update"),
threadId: thread.id,
title: event.payload.name,
titleSummaryState: "generated",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Provider metadata update unconditionally overrides manual title state

Medium Severity

When the provider emits a thread.metadata.updated event with a name, the code unconditionally sets titleSummaryState: "generated". This overwrites a user's "manual" state if they had previously renamed the thread. Since the new automatic title generation skips threads with "manual" state (by design), this could cause unexpected re-generation or misrepresent the origin of the title.

Fix in Cursor Fix in Web

@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Mar 24, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

There are 4 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

return yield* new RouteRequestError({
message: "Thread has no user messages to summarize.",
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Race condition: title generation reads stale projection snapshot

High Severity

generateThreadTitle reads thread messages via projectionReadModelQuery.getSnapshot(), which queries the asynchronously-updated projection database. When maybeGenerateFirstThreadTitle fires right after the thread.turn.start dispatch returns, the projection pipeline likely hasn't processed the thread.message-sent event yet, so userMessages is empty and the function fails with "Thread has no user messages to summarize." The synchronous in-memory read model (orchestrationEngine.getReadModel()) would have the message immediately, since the engine updates it before resolving the dispatch.

Additional Locations (1)
Fix in Cursor Fix in Web

generateCommitMessage,
generatePrContent,
generateBranchName,
generateThreadTitle,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Indentation inconsistency in return object literal

Low Severity

generateThreadTitle on line 539 uses 4-space indentation while the sibling properties (generateCommitMessage, generatePrContent, generateBranchName) use 6-space indentation in the returned object literal. This is a minor formatting inconsistency in the satisfies TextGenerationShape return block.

Fix in Cursor Fix in Web

@juliusmarminge

Copy link
Copy Markdown
Member

is there a real use case when people would want different models to generate titles than commit messages or can it all be one setting to control text generation for everything?

@maria-rcks

Copy link
Copy Markdown
Collaborator Author

is there a real use case when people would want different models to generate titles than commit messages or can it all be one setting to control text generation for everything?

so use the same as the git commit one but just reword the ui?

@maria-rcks

Copy link
Copy Markdown
Collaborator Author

also this pr is a mess, i think i'll open another one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: support ai generated thread names

3 participants