use super::super::super::ShellState;
use crate::AppModel;
use crate::boundary::{Gesture, codec};
use crate::cli_outbound::Cli;
use crate::git_tree::tests::fixture::Fixture;
use crate::ui_state::UiState;
use crate::wire::link::LinkEnd;
use crate::wire::post::Outbox;
use std::path::PathBuf;
use tempfile::TempDir;
pub(in crate::shell::acceptance) struct World {
pub(super) _root: TempDir,
pub(super) fx: Fixture,
pub(super) spheres: Vec<Fixture>,
pub(in crate::shell::acceptance) model: AppModel,
pub(super) deriver: crate::app::Deriver,
pub(in crate::shell::acceptance) state: ShellState,
pub(in crate::shell::acceptance) ws: PathBuf,
pub(in crate::shell::acceptance) yog_data: PathBuf,
pub(super) lernie_workspaces: PathBuf,
pub(in crate::shell::acceptance) link: LinkEnd,
pub(in crate::shell::acceptance) outbox: Outbox,
pub(super) lernie: Cli,
pub(super) bl: Cli,
}
impl World {
pub(in crate::shell::acceptance) fn converge(&mut self) {
self.acts();
self.deriver.step();
self.model.refresh();
}
pub(in crate::shell::acceptance) fn substrate(&mut self, lernie: &Cli, bl: &Cli) {
self.lernie = lernie.clone();
self.bl = bl.clone();
}
pub(in crate::shell::acceptance) fn acts(&mut self) -> bool {
let deps = self.model.boundary_deps(&self.lernie, &self.bl);
let ts = crate::shell::now_ts();
let mut answered = false;
while let Some((ticket, envelope)) = self.outbox.try_next() {
answered = true;
let landed = match codec::decode(&envelope) {
Ok(Gesture::Act(action)) => {
let mut ui = UiState::open(self.model.ui_json_path());
crate::boundary::dispatch::dispatch(&deps, &mut ui, &ts, &action)
}
Ok(Gesture::Ask(_)) => Err("the act path carries no reads".to_owned()),
Err(said) => Err(said),
};
self.outbox.publish(ticket, landed);
}
answered
}
pub(in crate::shell::acceptance) fn reads(&mut self) {
let deps = self.model.boundary_deps(&self.lernie, &self.bl);
let now = crate::shell::now_unix();
for question in self.link.standing() {
let landed = match codec::decode(&question) {
Ok(Gesture::Ask(query)) => self.model.answer(&deps, &query, now),
Ok(Gesture::Act(_)) => Err("the read path carries no acts".to_owned()),
Err(said) => Err(said),
};
self.link.publish(&question, landed);
}
}
pub(in crate::shell::acceptance) fn searches(&mut self) {
let Some((seq, text)) = self.model.search_cell().pending() else {
return;
};
let snap = self.model.derivation().clone();
self.model
.search_cell()
.publish(seq, crate::search::run(&snap, &text, &|| true));
}
pub(in crate::shell::acceptance) fn settle(&mut self) {
self.model.refresh();
self.reads();
self.acts();
self.searches();
}
pub(in crate::shell::acceptance) fn drain(&mut self, frame: &mut dyn FnMut(&mut Self)) {
loop {
self.model.refresh();
let waiting = self.model.awaiting();
self.reads();
let acted = self.acts();
self.searches();
if !waiting && !acted {
return;
}
frame(self);
self.model.refresh();
frame(self);
}
}
pub(in crate::shell::acceptance) fn add_workspace(
&mut self,
name: &str,
agent: &str,
) -> PathBuf {
let fx = Fixture::new();
fx.build_agent(agent, name);
let ws = self.lernie_workspaces.join(name);
std::os::unix::fs::symlink(&fx.path, &ws).unwrap();
self.spheres.push(fx);
ws
}
pub(in crate::shell::acceptance) fn add_child(&self, parent_id: &str, child_id: &str) {
self.fx.build_child(parent_id, child_id);
}
pub(in crate::shell::acceptance) fn add_root(&self, conv_id: &str, name: &str) {
self.fx.build_agent(conv_id, name);
self.fx.name_agent(conv_id, name);
}
pub(in crate::shell::acceptance) fn advance_config(&self, providers_yaml: &str) {
self.fx.commit_other("providers.yaml", providers_yaml);
}
pub(in crate::shell::acceptance) fn quiet(&self, conv_id: &str) {
self.fx
.mark_ref(&format!("refs/lernie/abandoned/{conv_id}"));
}
}