fix(agent-mode): correct session tab titles for codex and Claude Code#2607
Merged
Conversation
codex named sessions after the raw first prompt, leaking the injected
<copilot-context> envelope into the tab title, and Claude Code fell back to the
backend display name ("Claude") because its SDK exposes no title API. Only
opencode summarizes its own titles.
Add a required `summarizesSessionTitle` flag to BackendDescriptor (opencode:
true, codex/claude: false). Backends that summarize keep trusting their
session/list and pushed session_info_update titles; the rest now derive the tab
label client-side from the user's first visible message (reusing
deriveChatTitleFromMessages) and ignore backend-provided titles. The derived
title is agent-sourced, so a user Rename still wins and the first message's
title is stable across later turns.
Closes logancyang/obsidian-copilot-preview#113
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 88895298fd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Address Codex review: sweepNativeSessions() merged listSessions titles into the recent-chats index for every backend, so a codex session whose first prompt carried attached context could still be discovered (and reopened) with the raw <copilot-context> title, bypassing the AgentSession-level gating. Gate the sweep on summarizesSessionTitle too: non-summarizing backends (codex, Claude Code) are skipped entirely since the sweep has no transcript to derive a clean title from. Their sessions are still indexed via flushIndexTouch, which uses the client-derived title. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the Agent Mode tab-title bug (P0): codex tabs showed the raw injected
<copilot-context>envelope and Claude Code tabs showed the backend name "Claude" instead of a conversation title. opencode was already correct.Closes logancyang/obsidian-copilot-preview#113
Root cause
Session titles were entirely backend-provided. Only opencode runs a title-summarizer agent, so only it returned clean titles. codex names a session after the first prompt it receives (which leads with our context envelope when notes are attached), and the Claude SDK exposes no title API at all.
Change
summarizesSessionTitle: booleantoBackendDescriptor(opencodetrue; codex / Claude Codefalse).session/listand pushedsession_info_updatetitles.deriveChatTitleFromMessageshelper (strips wikilinks, truncates), and ignore any backend-provided title (pollSessionTitleand thesession_info_updatehandler are gated).A single
backendSummarizesTitle()helper centralizes the check; it defaults totruewhen no descriptor is wired (legacy/test construction) so existing opencode-path tests are unaffected.Tests
AgentSession client-derived title (non-summarizing backends)suite: codex/Claude derive from the first message, wikilink stripping, first-message stability across turns, user-rename precedence, opencode does not derive, pushed/polled titles ignored for non-summarizing backends.tscandeslintclean.Notes
🤖 Generated with Claude Code