use crate::boundary::{Action, Gesture, Query};
use crate::start::{BallSpec, Payload};
pub fn spell(gesture: &Gesture) -> String {
match gesture {
Gesture::Act(action) => spell_action(action),
Gesture::Ask(query) => spell_query(query),
}
}
fn spell_action(action: &Action) -> String {
match action {
Action::Message { content, .. } => format!("/message {content}"),
Action::Stop { children, .. } => match children {
true => "/stop children".to_owned(),
false => "/stop".to_owned(),
},
Action::Scan { .. } => "/scan".to_owned(),
Action::Close { id, .. } => format!("/close {id}"),
Action::Assign { id, .. } => format!("/assign {id}"),
Action::Release { id, .. } => format!("/release {id}"),
Action::Move { id, to, .. } => format!("/move {id} {to}"),
Action::Create { title, body, .. } => {
format!("/create {title}{}", flag("body", body.as_ref()))
}
Action::Update {
id,
title,
body,
note,
..
} => format!(
"/update {id}{}{}{}",
flag("title", title.as_ref()),
flag("body", body.as_ref()),
flag("note", note.as_ref())
),
Action::Prepare { payload, .. } => spell_payload(payload),
Action::Prompt { goal, .. } => format!("/prompt {goal}"),
Action::DeleteWorkspace { typed, .. } => format!("/delete-workspace {typed}"),
Action::DeleteAgent { typed, .. } if typed.is_empty() => "/delete-agent".to_owned(),
Action::DeleteAgent { typed, .. } => format!("/delete-agent {typed}"),
Action::Monitor(verb) => spell_monitor(verb),
Action::Fleet(verb) => spell_fleet(verb),
Action::AnswerHold { ruling, .. } => format!("/answer {}", ruling.word()),
Action::Floor { raised, .. } => match raised {
true => "/revoke".to_owned(),
false => "/restore".to_owned(),
},
Action::ApplyConfig { file, text } => {
format!("/config {} {text}", super::config::target_words(file))
}
Action::SetMarks { branch, .. } => format!("/marks {branch}"),
Action::PickModel {
role,
provider,
model,
..
} => format!("/model {role} {provider} {model}"),
Action::Fork { attempt, goal, .. } => super::fork::spell(attempt, goal),
Action::Ack => "/ack".to_owned(),
Action::MarkSeen { .. } => "/seen".to_owned(),
Action::ClearTrail => "/clear-trail".to_owned(),
}
}
fn spell_monitor(verb: &crate::monitor::Verb) -> String {
use crate::monitor::Verb;
match verb {
Verb::Arm { model, .. } => format!("/arm {model}"),
Verb::Disarm { .. } => "/disarm".to_owned(),
Verb::Flag { reason, .. } => format!("/flag {reason}"),
}
}
fn spell_fleet(verb: &crate::fleet::Verb) -> String {
use crate::fleet::Verb;
match verb {
Verb::Arm { cap, .. } => format!("/{} {cap}", crate::boundary::codec::FLEET_ARM),
Verb::Disarm { .. } => format!("/{}", crate::boundary::codec::FLEET_DISARM),
}
}
fn spell_query(query: &Query) -> String {
match query {
Query::Workspaces => "/workspaces".to_owned(),
Query::Conversations { .. } => "/conversations".to_owned(),
Query::Balls => "/balls".to_owned(),
Query::WorkDiff { file, .. } => match file {
Some(file) => format!("/work-diff {} {}", file.ball, file.path),
None => "/work-diff".to_owned(),
},
Query::Board => "/board".to_owned(),
Query::Attention => "/attention".to_owned(),
Query::Ops { max } => format!("/ops {max}"),
Query::Search { text } => format!("/search {text}"),
Query::Help { verb } => match verb {
Some(verb) => format!("/help {verb}"),
None => "/help".to_owned(),
},
Query::ReadConfig { file } => format!("/config {}", super::config::target_words(file)),
Query::Marks { .. } => "/marks".to_owned(),
Query::Providers { .. } => "/providers".to_owned(),
}
}
fn spell_payload(payload: &Payload) -> String {
match payload {
Payload::Bare => "/prepare".to_owned(),
Payload::Path { dir } => format!("/prepare dir {}", dir.display()),
Payload::Ball { ball, .. } => match ball {
BallSpec::Existing { .. } => "/prepare ball".to_owned(),
BallSpec::New { title, body } => format!(
"/prepare ball --new {title}{}",
flag("body", Some(body).filter(|b| !b.is_empty()))
),
},
}
}
fn flag(key: &str, value: Option<&String>) -> String {
match value {
Some(text) => format!(" --{key} {text}"),
None => String::new(),
}
}