Skip to content

Add conversation titles and rename support#49

Open
404-Page-Found wants to merge 9 commits into
mainfrom
26-add-conversation-titles-and-rename-support
Open

Add conversation titles and rename support#49
404-Page-Found wants to merge 9 commits into
mainfrom
26-add-conversation-titles-and-rename-support

Conversation

@404-Page-Found
Copy link
Copy Markdown
Collaborator

Closes #26

Summary

Conversation persistence previously stored only the message transcript in ~/.agent/history.yaml, so saved chats had no human-friendly titles or metadata. This PR adds auto-generated titles, a rename command, and title persistence.

What Changed

  • Auto-generated titles: When the first user message arrives, its content (truncated to 60 chars) becomes the conversation title.
  • Rename from TUI: New "Rename conversation" command in the command palette (Ctrl+K) opens a text prompt to set a custom title.
  • Title persistence: The title field is stored alongside messages in history.yaml and archived transcript files.
  • Backward compatibility: Existing transcripts without a title load correctly; the title is auto-generated on the next message. Archived transcripts without titles continue to show their preview text as the label.

Files Modified

File Change
src/core/transcript-store.ts Added title to transcript YAML schema, updated load/save/archive functions, added renameTranscript()
src/core/state-manager.ts Added title to snapshot, initialTitle to options, setTitle() method
src/tui/session.ts Title auto-generation from first user message, rename command, title propagation through save/archive
src/tui/App.tsx Rename prompt UI, title passed to StatusBar
src/tui/StreamingRenderer.tsx StatusBar displays title when present

Validation

  • npm run build passes (TypeScript compilation)
  • npm run lint passes (ESLint)

Risks / Follow-ups

  • Titles are derived from the first user message content, not from an LLM call. This is fast but may produce less descriptive titles than an AI-generated approach.
  • The renameTranscript() function in transcript-store.ts is no longer called externally (rename is handled entirely through state.setTitle + persistConversation). It can be removed in a follow-up if desired.

- Auto-generate titles from first user message (truncated to 60 chars)
- Add rename command to TUI command palette (Ctrl+K)
- Persist title alongside transcript in history.yaml
- Display title in StatusBar and TranscriptBrowser
- Backward compatible: existing transcripts without titles load correctly

Closes #26
@404-Page-Found 404-Page-Found requested a review from LWWZH as a code owner May 19, 2026 09:58
@404-Page-Found 404-Page-Found linked an issue May 19, 2026 that may be closed by this pull request
…anscripts

- Update currentTitle before setTitle in rename so persistConversation captures the new value
- Call setTitle after replaceConversation when loading archived transcripts
- Remove unused renameTranscript and syncTitle functions
@404-Page-Found
Copy link
Copy Markdown
Collaborator Author

Fixed three bugs identified during review:

  1. Rename not persisting title to disk - Set currentTitle before calling state.setTitle() so persistConversation captures the new value instead of the stale one.

  2. Loading archived transcript loses title in UI - Call state.setTitle() after state.replaceConversation() since replaceConversation unconditionally resets title to undefined.

  3. Dead code removal - Removed renameTranscript from transcript-store.ts (no longer called externally) and the now-unused syncTitle helper from session.ts.

- Batch replaceConversation + setTitle to avoid double persist on transcript load
- Pass title through onConversationChange callback instead of relying on closure state
- Truncate renamed titles to 60 chars to match auto-generated title behavior
- Remove redundant .or(z.undefined()) on archiveIndexEntrySchema.title
@404-Page-Found
Copy link
Copy Markdown
Collaborator Author

Pushed fixes for the review findings:

  • Bug 1: Captured \currentTitle\ by value (\savedTitle) in async queue callbacks for both \persistConversation\ and \�rchiveConversation\ to prevent stale title writes when title changes happen in quick succession.
  • Bug 2: Added \lastWriteSucceeded\ tracking so
    enameCurrentConversation\ reports the correct status instead of always showing success when the file write fails.
  • Minor: Renamed \currentTranscriptEntry\ → \currentTranscriptEntries\ to reflect that it's an array.

@404-Page-Found
Copy link
Copy Markdown
Collaborator Author

Patches Applied

Fix 1: Auto-generated title uses wrong message on transcript continuation

File: \src/tui/session.ts:422\

When loading an archived transcript without a title, \ itleGenerated\ is now set to \ rue\ immediately instead of waiting for the next message. This prevents auto-generation from deriving the title from the first user message in the entire history (which could be months old). The transcript browser already falls back to preview text for display, so no user-facing regression.

Fix 2: \lastWriteSucceeded\ could reflect a different write

Files: \src/tui/session.ts:106-166,543-548, \src/core/state-manager.ts:22-37\

Replaced the shared \lastWriteSucceeded\ boolean with a \Promise\ chain. Each write now carries its own success/failure through the queue, so \waitForTranscriptWrites()\ returns whether the actual queued write succeeded, not whatever happened to set the flag last.

Build and lint pass.

@LWWZH LWWZH removed their request for review May 31, 2026 07:08
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.

Add conversation titles and rename support

1 participant