Skip to content

fix(core): label untitled sessions by their first prompt - #57624

Open
opencode-agent[bot] wants to merge 2 commits into
devfrom
title-prompt-fallback
Open

opencode-agent[bot] wants to merge 2 commits into
devfrom
title-prompt-fallback

Conversation

@opencode-agent

Copy link
Copy Markdown
Contributor

Summary

When title generation is disabled (no title agent) or every title attempt fails, root sessions previously kept no title, so clients showed a placeholder: New session - <ISO timestamp> in the TUI, New session in 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).

  • A prompt-derived title still counts as untitled, so the next turn keeps retrying generation the same way an empty title does today. The runner now calls SessionTitle.ensure, which runs only while a session is untitled or still labeled by its first prompt. Explicit regeneration (generate) is unchanged.
  • A blank first prompt leaves the session untitled. Regenerating an existing real title that fails still keeps that title.
  • The rename uses the same sequence guard as generated titles, so a manual rename made while generation is running still wins.
  • Clients only use the timestamp fallback to swap in a placeholder (tab label, terminal title, mini splash), so no client changes are needed.

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/ in packages/core: all pass except Session.create > runs a shell command…, which fails the same way on origin/dev and is unrelated.
  • bun run typecheck in packages/core.

Requested by: @rekram1-node (Aiden Cline via Slack)

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.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Before

After

// 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) ||

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant