mirror of
https://github.com/openai/codex.git
synced 2026-05-22 03:54:18 +00:00
Addresses #23181 ## Why Renamed threads can share names, so hints that suggest resuming directly by name are ambiguous. Issue #23181 asks for the picker hint to include the thread name and thread ID in parens so users can disambiguate safely. ## What - Adds a shared resume hint formatter for named threads: run `codex resume`, then select `<name> (<thread-id>)`. - Uses that hint for /rename confirmations, TUI session summaries, and CLI/TUI exit messages. - Keeps direct `codex resume <thread-id>` guidance for unnamed threads. ## Verification Manually verified that message after `/rename` and after `/exit` include session ID in parens. --------- Co-authored-by: Felipe Coury <felipe.coury@openai.com>
104 lines
3.5 KiB
Rust
104 lines
3.5 KiB
Rust
//! Shared formatting for user-facing `codex resume` command hints.
|
|
|
|
use codex_protocol::ThreadId;
|
|
use codex_shell_command::parse_command::shlex_join;
|
|
|
|
pub fn resume_command(thread_name: Option<&str>, thread_id: Option<ThreadId>) -> Option<String> {
|
|
let resume_target = thread_name
|
|
.filter(|name| !name.is_empty())
|
|
.map(str::to_string)
|
|
.or_else(|| thread_id.map(|thread_id| thread_id.to_string()));
|
|
resume_target.map(|target| {
|
|
let needs_double_dash = target.starts_with('-');
|
|
let escaped = shlex_join(&[target]);
|
|
if needs_double_dash {
|
|
format!("codex resume -- {escaped}")
|
|
} else {
|
|
format!("codex resume {escaped}")
|
|
}
|
|
})
|
|
}
|
|
|
|
pub fn resume_hint(thread_name: Option<&str>, thread_id: Option<ThreadId>) -> Option<String> {
|
|
let thread_id = thread_id?;
|
|
match thread_name.filter(|name| !name.is_empty()) {
|
|
Some(thread_name) => Some(format!(
|
|
"codex resume, then select {thread_name} ({thread_id})"
|
|
)),
|
|
None => resume_command(/*thread_name*/ None, Some(thread_id)),
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[test]
|
|
fn prefers_name_over_id() {
|
|
let thread_id = ThreadId::from_string("123e4567-e89b-12d3-a456-426614174000").unwrap();
|
|
let command = resume_command(Some("my-thread"), Some(thread_id));
|
|
assert_eq!(command, Some("codex resume my-thread".to_string()));
|
|
}
|
|
|
|
#[test]
|
|
fn formats_thread_id_when_name_is_missing() {
|
|
let thread_id = ThreadId::from_string("123e4567-e89b-12d3-a456-426614174000").unwrap();
|
|
let command = resume_command(/*thread_name*/ None, Some(thread_id));
|
|
assert_eq!(
|
|
command,
|
|
Some("codex resume 123e4567-e89b-12d3-a456-426614174000".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn returns_none_without_a_resume_target() {
|
|
let command = resume_command(/*thread_name*/ None, /*thread_id*/ None);
|
|
assert_eq!(command, None);
|
|
}
|
|
|
|
#[test]
|
|
fn quotes_thread_names_when_needed() {
|
|
let command = resume_command(Some("-starts-with-dash"), /*thread_id*/ None);
|
|
assert_eq!(
|
|
command,
|
|
Some("codex resume -- -starts-with-dash".to_string())
|
|
);
|
|
|
|
let command = resume_command(Some("two words"), /*thread_id*/ None);
|
|
assert_eq!(command, Some("codex resume 'two words'".to_string()));
|
|
|
|
let command = resume_command(Some("quote'case"), /*thread_id*/ None);
|
|
assert_eq!(command, Some("codex resume \"quote'case\"".to_string()));
|
|
}
|
|
|
|
#[test]
|
|
fn resume_hint_names_picker_item_with_id() {
|
|
let thread_id = ThreadId::from_string("123e4567-e89b-12d3-a456-426614174000").unwrap();
|
|
let hint = resume_hint(Some("my-thread"), Some(thread_id));
|
|
assert_eq!(
|
|
hint,
|
|
Some(
|
|
"codex resume, then select my-thread (123e4567-e89b-12d3-a456-426614174000)"
|
|
.to_string()
|
|
)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn resume_hint_uses_direct_id_command_without_name() {
|
|
let thread_id = ThreadId::from_string("123e4567-e89b-12d3-a456-426614174000").unwrap();
|
|
let hint = resume_hint(/*thread_name*/ None, Some(thread_id));
|
|
assert_eq!(
|
|
hint,
|
|
Some("codex resume 123e4567-e89b-12d3-a456-426614174000".to_string())
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn resume_hint_requires_thread_id() {
|
|
let hint = resume_hint(Some("my-thread"), /*thread_id*/ None);
|
|
assert_eq!(hint, None);
|
|
}
|
|
}
|