use claude_wrapper::{Effort, PermissionMode, QueryCommand, RetryPolicy};
use crate::cli::{AskArgs, EffortLevel, PermMode};
pub fn apply_session(mut cmd: QueryCommand, args: &AskArgs) -> QueryCommand {
match &args.continue_session {
None => {} Some(None) => cmd = cmd.continue_session(), Some(Some(id)) => cmd = cmd.resume(id.clone()), }
if args.fork {
cmd = cmd.fork_session();
}
if let Some(m) = &args.model {
cmd = cmd.model(m.clone());
}
if let Some(e) = args.effort {
cmd = cmd.effort(match e {
EffortLevel::Low => Effort::Low,
EffortLevel::Medium => Effort::Medium,
EffortLevel::High => Effort::High,
EffortLevel::Xhigh => Effort::Xhigh,
EffortLevel::Max => Effort::Max,
});
}
if let Some(name) = &args.agent {
cmd = cmd.agent(name.clone());
}
if let Some(name) = &args.worktree {
cmd = match name {
Some(n) => cmd.worktree_named(n.clone()),
None => cmd.worktree(),
};
}
if let Some(ref text) = args.system_prompt {
cmd = cmd.system_prompt(text.clone());
}
if let Some(ref text) = args.append_system_prompt {
cmd = cmd.append_system_prompt(text.clone());
}
if args.show_thinking {
cmd = cmd.include_partial_messages();
}
if args.no_retry {
cmd = cmd.retry(RetryPolicy::new().max_attempts(1));
}
if args.bare {
cmd = cmd.bare();
}
apply_permissions(cmd, args)
}
pub fn apply_permissions(mut cmd: QueryCommand, args: &AskArgs) -> QueryCommand {
if args.full_auto {
return cmd.dangerously_skip_permissions();
}
if let Some(mode) = args.permission_mode {
let cw_mode = permission_mode_to_cw(mode);
cmd = cmd.permission_mode(cw_mode);
}
let mut allow: Vec<String> = vec!["Read".to_string(), "Glob".to_string(), "Grep".to_string()];
if args.writable {
push_unique(&mut allow, "Edit");
push_unique(&mut allow, "Write");
}
for t in &args.allow_tool {
push_unique(&mut allow, t);
}
cmd = cmd.allowed_tools(allow);
if !args.deny_tool.is_empty() {
cmd = cmd.disallowed_tools(args.deny_tool.clone());
}
cmd
}
fn permission_mode_to_cw(mode: PermMode) -> PermissionMode {
match mode {
PermMode::AcceptEdits => PermissionMode::AcceptEdits,
PermMode::Auto => PermissionMode::Auto,
#[allow(deprecated)]
PermMode::BypassPermissions => PermissionMode::BypassPermissions,
PermMode::Default => PermissionMode::Default,
PermMode::DontAsk => PermissionMode::DontAsk,
PermMode::Plan => PermissionMode::Plan,
}
}
fn push_unique(list: &mut Vec<String>, item: &str) {
if !list.iter().any(|s| s == item) {
list.push(item.to_string());
}
}
pub fn derive_session_name(prompt: &str) -> String {
let first_line = prompt
.lines()
.map(str::trim)
.find(|line| !line.is_empty())
.unwrap_or("");
let preview: String = if first_line.chars().count() > 40 {
let head: String = first_line.chars().take(40).collect();
format!("{head}…")
} else {
first_line.to_string()
};
if preview.is_empty() {
"roba".to_string()
} else {
format!("roba: {preview}")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn name_short_prompt_passes_through() {
assert_eq!(derive_session_name("hello"), "roba: hello");
}
#[test]
fn name_truncates_at_40_chars_with_ellipsis() {
let prompt = "this is a fairly long prompt that should get cut off somewhere";
let name = derive_session_name(prompt);
assert!(name.starts_with("roba: "), "got: {name}");
assert!(name.ends_with('…'), "got: {name}");
let body = name.trim_start_matches("roba: ").trim_end_matches('…');
assert_eq!(body.chars().count(), 40, "got body: {body:?}");
}
#[test]
fn name_uses_first_nonempty_line() {
let prompt = "\n\n \nthe real prompt\nignored continuation";
assert_eq!(derive_session_name(prompt), "roba: the real prompt");
}
#[test]
fn name_empty_prompt_falls_back_to_bare_roba() {
assert_eq!(derive_session_name(""), "roba");
assert_eq!(derive_session_name(" \n \n"), "roba");
}
#[test]
fn name_handles_unicode_correctly() {
let prompt = "あ".repeat(50);
let name = derive_session_name(&prompt);
let body = name.trim_start_matches("roba: ").trim_end_matches('…');
assert_eq!(body.chars().count(), 40);
}
}