use crate::commands::{BuiltInCommand, CommandRegistry, ParsedSlashCommand, parse_slash_command};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(in crate::tui) enum SubmitDecision {
Accept,
IgnoreEmpty,
QueueSteering,
}
#[derive(Debug, PartialEq, Eq)]
pub(in crate::tui) enum TuiSubmitCommand<'a> {
Compact(Option<&'a str>),
Changes,
Rewind(Option<&'a str>),
Help,
Login(Option<&'a str>),
Logout(Option<&'a str>),
Model(Option<&'a str>),
Models(Option<&'a str>),
Usage(Option<&'a str>),
Mcp(Option<&'a str>),
Tools(Option<&'a str>),
Subagents(Option<&'a str>),
Skills,
Sessions(Option<&'a str>),
SystemPrompt,
New,
PruneSessions(Option<&'a str>),
Quit,
Unsupported(&'a str),
None,
}
impl TuiSubmitCommand<'_> {
pub(in crate::tui) fn requires_idle(&self) -> bool {
matches!(
self,
Self::Compact(_)
| Self::Rewind(_)
| Self::Login(_)
| Self::Logout(_)
| Self::Model(_)
| Self::Models(_)
| Self::Usage(_)
| Self::Mcp(_)
| Self::Tools(_)
| Self::Subagents(_)
| Self::Skills
| Self::Sessions(_)
| Self::PruneSessions(_)
| Self::New
)
}
pub(in crate::tui) fn active_run_error(&self) -> Option<&'static str> {
match self {
Self::Compact(_) => Some("cannot compact while a prompt is running"),
Self::Rewind(_) => Some("cannot rewind while a prompt is running"),
Self::Login(_) => Some("cannot start login while a prompt is running"),
Self::Logout(_) => Some("cannot logout while a prompt is running"),
Self::Model(_) => Some("cannot change model while a prompt is running"),
Self::Models(_) => Some("cannot manage models while a prompt is running"),
Self::Usage(_) => Some("wait for the active run to finish before opening usage"),
Self::Mcp(_) => Some("cannot manage MCP servers while a prompt is running"),
Self::Tools(_) => Some("cannot manage tools while a prompt is running"),
Self::Subagents(_) => Some("cannot manage subagents while a prompt is running"),
Self::Skills => Some("cannot manage skills while a prompt is running"),
Self::Sessions(_) => Some("cannot switch sessions while a prompt is running"),
Self::PruneSessions(_) => Some("cannot prune sessions while a prompt is running"),
Self::New => Some("cannot start a new session while a prompt is running"),
Self::SystemPrompt
| Self::Changes
| Self::Help
| Self::Quit
| Self::Unsupported(_)
| Self::None => None,
}
}
}
pub(in crate::tui) fn tui_submit_command<'a>(
prompt: &'a str,
commands: &CommandRegistry,
) -> TuiSubmitCommand<'a> {
match parse_slash_command(prompt, commands) {
ParsedSlashCommand::Empty | ParsedSlashCommand::Prompt(_) => TuiSubmitCommand::None,
ParsedSlashCommand::Unknown { token } => TuiSubmitCommand::Unsupported(token),
ParsedSlashCommand::BuiltIn { command, arg } => match command {
BuiltInCommand::Help => TuiSubmitCommand::Help,
BuiltInCommand::Login => TuiSubmitCommand::Login(arg),
BuiltInCommand::Logout => TuiSubmitCommand::Logout(arg),
BuiltInCommand::Compact => TuiSubmitCommand::Compact(arg),
BuiltInCommand::Changes => TuiSubmitCommand::Changes,
BuiltInCommand::Rewind => TuiSubmitCommand::Rewind(arg),
BuiltInCommand::New => TuiSubmitCommand::New,
BuiltInCommand::Model => TuiSubmitCommand::Model(arg),
BuiltInCommand::Models => TuiSubmitCommand::Models(arg),
BuiltInCommand::Usage => TuiSubmitCommand::Usage(arg),
BuiltInCommand::Mcp => TuiSubmitCommand::Mcp(arg),
BuiltInCommand::Tools => TuiSubmitCommand::Tools(arg),
BuiltInCommand::Subagents => TuiSubmitCommand::Subagents(arg),
BuiltInCommand::SystemPrompt => TuiSubmitCommand::SystemPrompt,
BuiltInCommand::Skills => TuiSubmitCommand::Skills,
BuiltInCommand::Sessions => TuiSubmitCommand::Sessions(arg),
BuiltInCommand::PruneSessions => TuiSubmitCommand::PruneSessions(arg),
BuiltInCommand::Quit => TuiSubmitCommand::Quit,
},
}
}
pub(in crate::tui) fn submit_decision(active_run: bool, prompt: &str) -> SubmitDecision {
if prompt.trim().is_empty() {
SubmitDecision::IgnoreEmpty
} else if active_run {
SubmitDecision::QueueSteering
} else {
SubmitDecision::Accept
}
}
#[cfg(test)]
pub(in crate::tui) fn slash_command_token(prompt: &str) -> Option<&str> {
match parse_slash_command(prompt, &CommandRegistry::mvp()) {
ParsedSlashCommand::BuiltIn { command, .. } => Some(match command {
BuiltInCommand::Help => "/help",
BuiltInCommand::Login => "/login",
BuiltInCommand::Logout => "/logout",
BuiltInCommand::Compact => "/compact",
BuiltInCommand::Changes => "/changes",
BuiltInCommand::Rewind => "/rewind",
BuiltInCommand::New => "/new",
BuiltInCommand::Model => "/setmodel",
BuiltInCommand::Models => "/models",
BuiltInCommand::Usage => "/usage",
BuiltInCommand::Mcp => "/mcp",
BuiltInCommand::Tools => "/tools",
BuiltInCommand::Subagents => "/subagents",
BuiltInCommand::SystemPrompt => "/system-prompt",
BuiltInCommand::Skills => "/skills",
BuiltInCommand::Sessions => "/sessions",
BuiltInCommand::PruneSessions => "/prune-sessions",
BuiltInCommand::Quit => "/quit",
}),
ParsedSlashCommand::Unknown { token } => Some(token),
ParsedSlashCommand::Empty | ParsedSlashCommand::Prompt(_) => None,
}
}
#[cfg(test)]
pub(in crate::tui) fn is_new_session_command(prompt: &str) -> bool {
matches!(
tui_submit_command(prompt, &CommandRegistry::mvp()),
TuiSubmitCommand::New
)
}
#[cfg(test)]
pub(in crate::tui) fn is_quit_command(prompt: &str) -> bool {
matches!(
tui_submit_command(prompt, &CommandRegistry::mvp()),
TuiSubmitCommand::Quit
)
}
#[cfg(test)]
pub(in crate::tui) fn unsupported_slash_command(prompt: &str) -> Option<&str> {
match tui_submit_command(prompt, &CommandRegistry::mvp()) {
TuiSubmitCommand::Unsupported(command) => Some(command),
_ => None,
}
}