Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions codex-rs/tui/src/bottom_pane/slash_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,16 @@ pub(crate) fn commands_for_input(
.collect()
}

/// Find a single built-in command by exact name, after applying feature gating.
/// Find a single built-in command by a recognized name or alias, after applying feature gating.
///
/// Side-conversation gating is intentionally enforced by dispatch rather than exact lookup so a
/// Side-conversation gating is intentionally enforced by dispatch rather than command lookup so a
/// typed command can produce a side-specific unavailable message while the popup still hides it.
pub(crate) fn find_builtin_command(name: &str, flags: BuiltinCommandFlags) -> Option<SlashCommand> {
let cmd = SlashCommand::from_str(name).ok()?;
let cmd = SlashCommand::from_str(name).ok().or_else(|| {
let repeated_os = name.strip_prefix('g')?.strip_suffix("al")?;
(!repeated_os.is_empty() && repeated_os.bytes().all(|byte| byte == b'o'))
.then_some(SlashCommand::Goal)
})?;
builtins_for_input(BuiltinCommandFlags {
side_conversation_active: false,
..flags
Expand Down Expand Up @@ -187,6 +191,14 @@ mod tests {
);
}

#[test]
fn goal_command_allows_extra_os_for_dispatch() {
assert_eq!(
find_builtin_command("goooooooooooal", all_enabled_flags()),
Some(SlashCommand::Goal)
);
}

#[test]
fn stop_command_resolves_for_dispatch() {
assert_eq!(
Expand Down
4 changes: 2 additions & 2 deletions codex-rs/tui/src/chatwidget/tests/slash_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,12 +599,12 @@ async fn inline_slash_command_is_available_from_local_recall_after_dispatch() {
}

#[tokio::test]
async fn goal_slash_command_emits_set_goal_event() {
async fn goal_slash_command_with_extra_os_emits_set_goal_event() {
let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
chat.set_feature_enabled(Feature::Goals, /*enabled*/ true);
let thread_id = ThreadId::new();
chat.thread_id = Some(thread_id);
let command = "/goal --tokens 98.5K improve benchmark coverage";
let command = "/goooooooooooal --tokens 98.5K improve benchmark coverage";

submit_composer_text(&mut chat, command);

Expand Down
Loading