use super::parse::ask;
use super::verbs::{max, work_file};
use super::{Context, args};
use crate::boundary::config::Read;
use crate::boundary::{Gesture, Query, help};
pub(super) const LOGIN_TAIL: &str = "login-tail";
pub(super) fn queries(verb: &str, tail: &str, ctx: &Context) -> Result<Gesture, String> {
if let Some(gesture) = conversation(verb, tail, ctx) {
return gesture;
}
match verb {
"workspaces" => args::none(tail, verb).map(|()| ask(Query::Workspaces)),
"conversations" => {
args::none(tail, verb)?;
Ok(ask(Query::Conversations {
workspace: args::workspace(ctx, verb)?,
}))
}
"balls" => args::none(tail, verb).map(|()| ask(Query::Balls)),
"workspace-balls" => {
args::none(tail, verb)?;
Ok(ask(Query::WorkspaceBalls {
workspace: args::workspace(ctx, verb)?,
}))
}
"work-diff" => Ok(ask(Query::WorkDiff {
workspace: args::workspace(ctx, verb)?,
file: work_file(tail, verb)?,
})),
"science" => {
args::none(tail, verb)?;
Ok(ask(Query::Science {
workspace: args::workspace(ctx, verb)?,
}))
}
"board" => args::none(tail, verb).map(|()| ask(Query::Board)),
"providers" => {
args::none(tail, verb)?;
Ok(ask(Query::Config(Read::Providers {
workspace: args::workspace(ctx, verb)?,
})))
}
"roles" => {
args::none(tail, verb)?;
Ok(ask(Query::Config(Read::Roles {
workspace: args::workspace(ctx, verb)?,
})))
}
"clients" => {
args::none(tail, verb)?;
Ok(ask(Query::Clients {
workspace: args::workspace(ctx, verb)?,
}))
}
"lineages" => {
args::none(tail, verb)?;
Ok(ask(Query::Config(Read::Lineages {
workspace: args::workspace(ctx, verb)?,
})))
}
"models" => Ok(ask(Query::Config(Read::Models {
workspace: args::workspace(ctx, verb)?,
provider: match args::optional_word(tail, verb)? {
Some(provider) => provider,
None => return Err(format!("/{verb}: usage: /models <provider>")),
},
}))),
"invocations" => args::none(tail, verb).map(|()| ask(Query::Invocations)),
"capture" => match args::optional_word(tail, verb)? {
Some(invocation) => Ok(ask(Query::Capture { invocation })),
None => Err(format!("/{verb}: usage: /{verb} <invocation>")),
},
LOGIN_TAIL => match args::optional_word(tail, verb)? {
Some(provider) => Ok(ask(Query::LoginTail {
workspace: args::workspace(ctx, verb)?,
provider,
})),
None => Err(format!("/{verb}: usage: /{verb} <provider>")),
},
"attention" => args::none(tail, verb).map(|()| ask(Query::Attention)),
"ops" => Ok(ask(Query::Ops { max: max(tail)? })),
"search" => Ok(ask(Query::Search {
text: tail.trim().to_owned(),
})),
other => Err(format!("unknown command /{other}\n{}", help::roster())),
}
}
fn conversation(verb: &str, tail: &str, ctx: &Context) -> Option<Result<Gesture, String>> {
Some(match verb {
"transcript" => bare(verb, tail, ctx, &|workspace, agent| Query::Transcript {
workspace,
agent,
}),
"follow" => bare(verb, tail, ctx, &|workspace, agent| Query::Follow {
workspace,
agent,
}),
"steps" => bare(verb, tail, ctx, &|workspace, agent| Query::Steps {
workspace,
agent,
}),
"rail" => bare(verb, tail, ctx, &|workspace, agent| Query::Rail {
workspace,
agent,
}),
"inbox" => bare(verb, tail, ctx, &|workspace, agent| Query::Inbox {
workspace,
agent,
}),
"agent" => bare(verb, tail, ctx, &|workspace, agent| Query::Agent {
workspace,
agent,
}),
"step" => step(verb, tail, ctx),
"files" => files(verb, tail, ctx),
"governing" => governing(verb, tail, ctx),
_ => return None,
})
}
fn bare(
verb: &str,
tail: &str,
ctx: &Context,
build: &dyn Fn(String, String) -> Query,
) -> Result<Gesture, String> {
args::none(tail, verb)?;
let (workspace, agent) = at(verb, ctx)?;
Ok(ask(build(workspace, agent)))
}
fn step(verb: &str, tail: &str, ctx: &Context) -> Result<Gesture, String> {
let Some(seq) = args::optional_word(tail, verb)? else {
return Err(format!("/{verb}: usage: /step <seq>"));
};
let (workspace, agent) = at(verb, ctx)?;
Ok(ask(Query::Step {
workspace,
agent,
seq,
}))
}
fn files(verb: &str, tail: &str, ctx: &Context) -> Result<Gesture, String> {
let (positional, flags) = args::split_flags(tail);
args::only(&flags, &["at"], verb)?;
let path = args::optional_word(&positional, verb)?;
let (workspace, agent) = at(verb, ctx)?;
Ok(ask(Query::Files {
workspace,
agent,
path,
at: args::flag(&flags, "at", verb)?,
}))
}
fn governing(verb: &str, tail: &str, ctx: &Context) -> Result<Gesture, String> {
let (positional, flags) = args::split_flags(tail);
args::none(&positional, verb)?;
args::only(&flags, &["at"], verb)?;
let (workspace, agent) = at(verb, ctx)?;
Ok(ask(Query::Governing {
workspace,
agent,
at: args::flag(&flags, "at", verb)?,
}))
}
fn at(verb: &str, ctx: &Context) -> Result<(String, String), String> {
Ok((args::workspace(ctx, verb)?, args::agent(ctx, verb)?))
}