docs(core): document session title generation

Document the new `[session_titles]` settings and clarify the thread-title generation internals with focused rustdoc comments.

This explains how generated names interact with `/rename`, when the background request is allowed to run, and why generated title values are sanitized before being persisted.
This commit is contained in:
Felipe Coury
2026-04-10 16:03:28 -03:00
parent d35a533e0f
commit eb367e3030
3 changed files with 44 additions and 0 deletions
+2
View File
@@ -213,7 +213,9 @@ pub struct SessionTitlesToml {
/// Effective session title settings after defaults are applied.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionTitlesConfig {
/// Whether interactive sessions should ask an auxiliary model for a default title.
pub enabled: bool,
/// Optional model override for the title-only background request.
pub model: Option<String>,
}
+24
View File
@@ -860,7 +860,9 @@ pub(crate) struct Session {
pub(crate) services: SessionServices,
js_repl: Arc<JsReplHandle>,
next_internal_sub_id: AtomicU64,
/// One-shot guard that prevents later user turns from spawning duplicate title requests.
thread_name_generation_started: AtomicBool,
/// Serializes manual and generated thread-name writes through the shared session-index path.
thread_name_write_lock: Mutex<()>,
}
@@ -4137,6 +4139,12 @@ impl Session {
});
}
/// Claims the one allowed background-title attempt for this session.
///
/// A generated name is only useful for persisted, interactive sessions that still
/// do not have a name. The name is checked again while committing it, so callers
/// may rely on this method only as the spawn gate; it is not the authority that
/// decides whether the generated value ultimately wins over `/rename`.
async fn should_start_thread_name_generation(&self) -> bool {
let (enabled, source_allows_generation, has_thread_name) = {
let state = self.state.lock().await;
@@ -4981,6 +4989,11 @@ async fn persist_thread_name_update(
Ok(msg)
}
/// Persists a thread name, updates session state, and notifies listeners as one ordered write.
///
/// Manual `/rename` passes [`SetThreadNameMode::Always`]. Generated titles pass
/// [`SetThreadNameMode::IfUnset`] so the state under the write lock can veto a
/// stale model result after the user has already named the thread.
async fn commit_thread_name(
sess: &Arc<Session>,
sub_id: String,
@@ -5034,6 +5047,11 @@ async fn commit_thread_name(
Ok(SetThreadNameOutcome::Updated)
}
/// Returns whether sessions from this entry point should be auto-titled from the first prompt.
///
/// Exec sessions and sub-agents usually have an enclosing task that names their
/// purpose, and generating extra names for them would spend a model request
/// without improving the interactive session list.
fn session_source_allows_thread_name_generation(session_source: &SessionSource) -> bool {
!matches!(
session_source,
@@ -5083,6 +5101,12 @@ async fn generate_and_set_thread_name(
.map_err(|err| anyhow::anyhow!("{err:?}"))
}
/// Runs the title-only model request and returns the raw title candidate.
///
/// The response is requested as JSON, but older or non-conforming providers can
/// still return text. Callers must sanitize the returned string before storing
/// it; persisting this raw value could leak quotes, markdown, or an overlong
/// summary into terminal titles and session pickers.
async fn generate_thread_name(
sess: &Session,
request: &ThreadNameGenerationRequest,
+18
View File
@@ -72,6 +72,24 @@ back to these environment variables.
Codex stores "do not show again" flags for some UI prompts under the `[notice]` table.
## Session titles
Interactive sessions generate a short default thread name after the first user prompt. The generated name uses the same storage and update event as `/rename`, and `/rename` still wins if the user names the thread before the background title request commits.
Disable default title generation with:
```toml
[session_titles]
enabled = false
```
Select the auxiliary model used for generated titles with:
```toml
[session_titles]
model = "gpt-5.4-mini"
```
## Plan mode defaults
`plan_mode_reasoning_effort` lets you set a Plan-mode-specific default reasoning