feat(threads): add title summary generation and settings - #1256
maria-rcks wants to merge 5 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Great work, id propose that we occasionally re-trigger to update the title? |
I thought about this but how do we measure when to re-trigger? Would love Julius comments on this. |
|
also could be a separate pr |
|
Happy for it to be a separate PR |
267b38f to
1b77529
Compare
| description: error instanceof Error ? error.message : "An error occurred.", | ||
| }); | ||
| }); | ||
| } |
There was a problem hiding this comment.
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)
| commandId: providerCommandId(event, "thread-meta-update"), | ||
| threadId: thread.id, | ||
| title: event.payload.name, | ||
| titleSummaryState: "generated", |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
There are 4 total unresolved issues (including 2 from previous reviews).
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.", | ||
| }); | ||
| } |
There was a problem hiding this comment.
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)
| generateCommitMessage, | ||
| generatePrContent, | ||
| generateBranchName, | ||
| generateThreadTitle, |
There was a problem hiding this comment.
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.
|
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? |
|
also this pr is a mess, i think i'll open another one |


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.
Checklist
closes #990
Note
Add automatic thread title generation via Codex with settings controls
generateThreadTitleWebSocket 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.titleSummaryState("missing","generated","manual") on threads throughout the stack: contracts, orchestration events, projections, DB migration, and local state.ChatViewwith an async call togenerateAndRenameThreadTitle, gated by the newtitleSummaryMode: 'automatic'app setting.title_summary_statecolumn and migration 017 to normalize legacypiAgentprovider names tocodexacross persisted rows and event JSON.titleSummaryStateto"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.generateThreadTitleWebSocket 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 theprojection_threadstable (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 asmanual, and a separatetitleSummaryModelsetting controls which model is used.Adds compatibility for legacy
piAgentprovider identifiers by normalizing them tocodexduring event-store replay and provider-session reads (plus a data migration), and hardens terminal state persistence to fall back to in-memory storage whenlocalStorageisn’t available.Written by Cursor Bugbot for commit 5e0a014. This will update automatically on new commits. Configure here.