#[derive(Debug, Clone)]
pub enum CommandResult {
None,
Output(String),
Error(String),
ModelChanged {
model: String,
},
ThinkingChanged {
level: String,
budget: u32,
},
SystemPromptSet {
source: String, },
SystemPromptShow {
prompt: String,
},
SessionList {
sessions: Vec<SessionSummary>,
},
Cleared,
Quit,
Compact,
Resumed {
session_id: String,
model: String,
},
Named {
name: String,
},
ChainInfo(String),
OpenModal(ModalRequest),
Status {
text: String,
},
PingStarted,
KeybindList(String),
SkillLoaded {
skill: std::sync::Arc<crate::skills::LoadedSkill>,
arg: String,
},
PluginCommand {
command: std::sync::Arc<crate::skills::registry::RegisteredPluginCommand>,
arg: String,
},
SidecarToggle { plugin_id: Option<String> },
SidecarStatus { plugin_id: Option<String> },
}
#[derive(Debug, Clone)]
pub enum ModalRequest {
Models,
Settings,
Plugins,
HelpFind { query: String },
Extensions { sub: String },
}
#[derive(Debug, Clone)]
pub struct SessionSummary {
pub id: String,
pub model: String,
pub title: Option<String>,
pub cost: f64,
pub message_count: usize,
pub is_current: bool,
}
pub fn parse_command(input: &str) -> Option<(&str, &str)> {
let trimmed = input.trim();
if !trimmed.starts_with('/') {
return None;
}
let without_slash = &trimmed[1..];
let (cmd, arg) = match without_slash.find(char::is_whitespace) {
Some(pos) => (&without_slash[..pos], without_slash[pos..].trim()),
None => (without_slash, ""),
};
Some((cmd, arg))
}
pub fn handle_engine_command(
cmd: &str,
arg: &str,
runtime: &mut crate::Runtime,
) -> Option<CommandResult> {
match cmd {
"model" if !arg.is_empty() => {
runtime.set_model(arg.to_string());
Some(CommandResult::ModelChanged {
model: arg.to_string(),
})
}
"thinking" if !arg.is_empty() => {
let (level, budget) = match arg {
"off" | "none" => ("off".to_string(), 0),
"adaptive" => ("adaptive".to_string(), 0),
"low" => ("low".to_string(), 2048),
"medium" | "med" => ("medium".to_string(), 4096),
"high" => ("high".to_string(), 16384),
"xhigh" | "max" => ("xhigh".to_string(), 32768),
other => {
if let Ok(n) = other.parse::<u32>() {
(format!("custom({})", n), n)
} else {
return Some(CommandResult::Error(
format!("unknown thinking level: {} (use off/adaptive/low/medium/high/xhigh or a number)", other)
));
}
}
};
runtime.set_thinking_budget(budget);
Some(CommandResult::ThinkingChanged { level, budget })
}
"quit" | "exit" => Some(CommandResult::Quit),
"compact" => Some(CommandResult::Compact),
_ => None, }
}