Repository navigation
fix(core): label untitled sessions by their first prompt - #57624
opencode-agent[bot] wants to merge 2 commits into
Conversation
When title generation is disabled or fails, root sessions kept no title and clients showed a timestamped placeholder. Store the first prompt (whitespace collapsed, truncated to 100 characters) instead, and keep treating that label as untitled so the next turn still retries generation.
There was a problem hiding this comment.
Looks good. In the TUI with the simulated model and a title model that returns nothing, the base leaves the tab as New session. With this change it shows the first prompt (screenshots below). The title and runner tests pass (255), and typecheck in packages/core is clean.
Public API: unchanged. SessionTitle.ensure is internal to core, and the event and HTTP shapes are the same.
One non-blocking edge case about finding the prompt title by its text is noted inline.
| // Labels a session whose title cannot be generated, instead of leaving a timestamped fallback. | ||
| const promptTitle = (text: string) => truncate(text.replace(/\s+/g, " ").trim()) | ||
| const isUntitled = (session: SessionSchema.Info, firstPrompt: string) => | ||
| session.title === promptTitle(firstPrompt) || |
There was a problem hiding this comment.
Non-blocking: the code decides a session is still untitled by comparing its title text to the prompt. So a title that only happens to equal the collapsed first prompt also counts as untitled. That covers a manual rename to exactly the prompt text, and a short prompt the title model echoes back unchanged. ensure would then regenerate it on the next turn, which overwrites the manual rename or sends one title request every turn. This is rare and probably acceptable, but it's worth knowing about.


Summary
When title generation is disabled (no
titleagent) or every title attempt fails, root sessions previously kept no title, so clients showed a placeholder:New session - <ISO timestamp>in the TUI,New sessionin the app. Finding a session by its first prompt is easier than by a timestamp.This change stores the first user prompt as the title in that case (whitespace collapsed, truncated to the existing 100-character title limit).
SessionTitle.ensure, which runs only while a session is untitled or still labeled by its first prompt. Explicit regeneration (generate) is unchanged.Note: for command sessions the first message is the expanded command template (the same text the title model receives), so a fallback title there starts with the template text.
Testing
bun test test/session-title.test.ts test/session-runner.test.ts test/session-*.test.ts test/integration.test.ts test/plugin/inpackages/core: all pass exceptSession.create > runs a shell command…, which fails the same way onorigin/devand is unrelated.bun run typecheckinpackages/core.Requested by: @rekram1-node (Aiden Cline via Slack)