use crate::actions::verbs;
use crate::model_pick::Pick;
use crate::names::SplitMix64;
use crate::start::{self, StartInputs};
use crate::ui_state::UiState;
use super::reply::Reply;
use super::{Action, answer, config, control, fleet, monitor};
mod delete_exec;
mod deps;
use delete_exec::{delete_agent, unmake};
pub use deps::Deps;
pub fn dispatch(deps: &Deps, ui: &mut UiState, ts: &str, action: &Action) -> Result<Reply, String> {
let (bl, root) = (&deps.bl, deps.state_root.as_path());
let outcome = |r: std::io::Result<verbs::Outcome>| -> Result<Reply, String> {
r.map(Reply::Outcome).map_err(|e| e.to_string())
};
match action {
Action::Message {
workspace: ws,
agent,
content,
} => outcome(verbs::message(&deps.bound(ws), root, ts, agent, content)),
Action::Stop {
workspace: ws,
agent,
children,
} => outcome(verbs::stop(&deps.bound(ws), root, ts, agent, *children)),
Action::Scan { workspace: ws } => outcome(verbs::scan(&deps.bound(ws), root, ts)),
Action::Fork {
workspace,
parent,
attempt,
goal,
} => fork(deps, ts, workspace, parent, attempt, goal),
Action::Close { project, id, name } => {
outcome(verbs::close(bl, root, ts, project, id, name))
}
Action::Assign { project, id, name } => {
outcome(verbs::assign(bl, root, ts, project, id, name))
}
Action::Release { project, id, name } => {
outcome(verbs::unclaim(bl, root, ts, project, id, name))
}
Action::Move {
project,
id,
from,
to,
} => outcome(verbs::reassign(bl, root, ts, project, id, from, to)),
Action::Create {
project,
title,
name,
body,
} => outcome(verbs::create(
bl,
root,
ts,
project,
title,
name,
body.as_deref(),
)),
Action::Update {
project,
id,
name,
title,
body,
note,
} => {
let fields = verbs::Update::of(title, body, note);
outcome(verbs::update(bl, root, ts, project, id, name, &fields))
}
Action::Prepare { workspace, payload } => {
prepare(deps, ts, workspace, payload).map(Reply::Prepared)
}
Action::Prompt { prepared, goal } => {
prompt(deps, ui, ts, prepared, goal).map(|conversation| Reply::Started { conversation })
}
Action::DeleteWorkspace { workspace, typed } => unmake(deps, ui, ts, workspace, typed),
Action::DeleteAgent {
workspace,
agent,
typed,
} => delete_agent(deps, ui, ts, workspace, agent, typed),
Action::Monitor(verb) => monitor::dispatch(deps, ts, verb),
Action::Fleet(verb) => fleet::dispatch(deps, ts, verb),
Action::AnswerHold {
workspace,
agent,
ruling,
} => control::answer_hold(deps, ts, workspace, agent, *ruling),
Action::Floor {
workspace,
agent,
raised,
} => control::set_floor(deps, ts, workspace, agent, *raised),
Action::Ack => wrote(crate::opslog::ack(root, ts), Reply::Acked),
Action::MarkSeen { workspace, agent } => acknowledge(deps, ui, ts, workspace, agent),
Action::ClearTrail => wrote(crate::opslog::clear(root, ts), Reply::TrailCleared),
Action::ApplyConfig { file, text } => config::apply(deps, ts, file, text),
Action::SetMarks { workspace, branch } => config::set_marks(deps, ts, workspace, branch),
Action::PickModel {
workspace,
role,
provider,
model,
} => config::pick_model(deps, ts, workspace, &Pick::of(role, provider, model)),
}
}
fn wrote(written: std::io::Result<()>, reply: Reply) -> Result<Reply, String> {
written.map(|()| reply).map_err(|e| e.to_string())
}
fn fork(
deps: &Deps,
ts: &str,
workspace: &std::path::Path,
parent: &str,
attempt: &crate::fork::Attempt,
goal: &str,
) -> Result<Reply, String> {
control::confinement_gate(workspace)?;
verbs::fork(
&deps.bound(workspace),
&deps.state_root,
ts,
&crate::fork::Fire::at(workspace, parent, attempt, goal, &deps.yog_data_root),
)
.map(Reply::Outcome)
.map_err(|e| e.to_string())
}
pub fn prepare(
deps: &Deps,
ts: &str,
workspace: &std::path::Path,
payload: &crate::start::Payload,
) -> Result<crate::start::Prepared, String> {
let inputs = StartInputs {
conversation_names: answer::names_in(&deps.snapshot, workspace),
workspace: workspace.to_path_buf(),
payload: payload.clone(),
home: deps.home.clone(),
yog_data_root: deps.yog_data_root.clone(),
balls_state_root: deps.balls_state_root.clone(),
};
let start_deps = start::Deps {
bl: deps.bl.clone(),
lernie: deps.lernie.clone(),
state_root: deps.state_root.clone(),
yog_binary: deps.yog_binary.clone(),
};
start::prepare(&start_deps, &inputs, ts).map_err(|e| e.to_string())
}
pub fn prompt(
deps: &Deps,
ui: &UiState,
ts: &str,
prepared: &crate::start::Prepared,
goal: &str,
) -> Result<String, String> {
control::confinement_gate(&prepared.workspace)?;
super::ceiling::gate(ui, &deps.state_root, ts, prepared)?;
let own_space = prepared.origin != crate::opslog::Origin::Balls;
let lernie = deps
.lernie
.and_env(crate::world::wall::pairs(&deps.world, &prepared.workspace))
.and_env(crate::world::marks::pairs(
&deps.world,
&prepared.workspace,
own_space,
));
start::execute_prompt(
&lernie,
&deps.state_root,
ts,
prepared,
goal,
&answer::names_in(&deps.snapshot, &prepared.workspace),
&mut SplitMix64::from_seed(deps.mint_seed),
)
.map_err(|e| e.to_string())
}
fn acknowledge(
deps: &Deps,
ui: &mut UiState,
ts: &str,
workspace: &std::path::Path,
agent: &str,
) -> Result<Reply, String> {
answer::queue::mark_seen(&deps.snapshot, ui, workspace, agent)?;
let rows = answer::queue::queue(&deps.snapshot, ui, ts.parse().unwrap_or(0));
Ok(Reply::Attention(rows))
}