use crate::ui_state::UiState;
use super::dispatch::Deps;
use super::reply::Reply;
use super::{Query, config, help, login};
pub mod agent;
pub mod balls;
mod chrome;
mod confirm;
pub mod convs;
pub mod inspector;
pub mod queue;
pub use chrome::{workspace_stats, workspaces, ws_rows};
pub use confirm::{agent_confirmation_of, confirmation_of};
pub use convs::{conv_ball, conversations, names_in};
pub fn answer(query: &Query, deps: &Deps, ui: &UiState, now_unix: i64) -> Result<Reply, String> {
let snap = &deps.snapshot;
let ws: &std::path::Path = &match query.workspace() {
Some(name) => snap.ws_path(&name)?,
None => std::path::PathBuf::new(),
};
let agent: &str = &super::address::resolve_agent(snap, ws, query.agent())?;
Ok(match query {
Query::Workspaces => Reply::Workspaces(workspaces(snap, ui, now_unix)),
Query::Conversations { .. } => Reply::Conversations(conversations(snap, ui, ws, now_unix)),
Query::Balls => Reply::Balls(snap.join_rows.clone()),
Query::WorkspaceBalls { .. } => Reply::WorkspaceBalls(balls::ws_balls(snap, ui, ws)),
Query::Board => Reply::Board(crate::board::build(snap, ui, now_unix)),
Query::Attention => Reply::Attention(queue::queue(snap, ui, now_unix)),
Query::Help { verb } => Reply::Help(help::rows(verb.as_deref())),
Query::Search { text } => Reply::Search(crate::search::run(snap, text, &|| true)),
Query::WorkDiff { file, .. } => {
let entries = crate::opslog::tail(&deps.state_root, usize::MAX);
let attempts = crate::workdiff::read(snap, ws, &entries, &deps.world);
let patch = file
.as_ref()
.and_then(|f| crate::workdiff::patch(snap, &attempts, f));
Reply::WorkDiff { attempts, patch }
}
Query::Science { .. } => {
let entries = crate::opslog::tail(&deps.state_root, usize::MAX);
Reply::Science(crate::science::project(snap, ws, &entries, &deps.world))
}
Query::Transcript { .. } => {
Reply::Transcript(inspector::transcript(snap, ws, agent, now_unix))
}
Query::Follow { .. } => Reply::Follow(super::follow::once(snap, ws, agent)),
Query::LoginTail { provider, .. } => login::standing(deps, ws, provider),
Query::Steps { .. } => Reply::Steps(inspector::steps(snap, ws, agent, now_unix)),
Query::Step { seq, .. } => Reply::Step(crate::steps_view::detail(ws, agent, seq)?),
Query::Files { path, at, .. } => {
let (view, preview) = inspector::files(ws, agent, path.as_deref(), at.as_deref());
Reply::Files {
view,
preview,
working_dir: inspector::working_dir(ws, agent),
}
}
Query::Rail { .. } => {
let steps = inspector::steps(snap, ws, agent, now_unix);
let tx = inspector::transcript(snap, ws, agent, now_unix);
Reply::Rail(inspector::rail(snap, ws, agent, &steps, &tx))
}
Query::Inbox { .. } => Reply::Inbox(crate::inboxview::list_inbox(ws, agent)),
Query::Governing { at, .. } => {
return inspector::governing(snap, ws, agent, at.as_deref()).map(Reply::Governing);
}
Query::Agent { .. } => Reply::Agent(agent::agent(snap, ui, ws, agent, now_unix)),
Query::Ops { max } => {
let skip = snap.ops.len().saturating_sub(*max);
let tail: Vec<crate::opslog::OpRow> = snap.ops.iter().skip(skip).cloned().collect();
Reply::Ops(crate::opslog::standings(&tail))
}
Query::Config(read) => {
return match read {
config::Read::File { file } => config::file(deps, ws, file),
config::Read::Marks { .. } => Ok(config::read_marks(deps, ws)),
config::Read::Providers { .. } => Ok(config::providers(deps, ws)),
config::Read::Lineages { .. } => config::lineages(ws),
config::Read::Models { provider, .. } => config::models(deps, ws, provider),
config::Read::Roles { .. } => Ok(config::roles(ws)),
config::Read::Proposals { id, .. } => config::proposals(ws, id.as_deref()),
};
}
Query::Clients { workspace } => Reply::Clients(crate::registry::roster::roster(
&deps.state_root,
&deps.caller.presence,
workspace,
)),
Query::Doctor { workspace } => Reply::Doctor(crate::doctor::examine(
deps,
workspace.as_deref().map(|name| (name, ws)),
)),
Query::Invocations => return super::routing::invocations(deps),
Query::Capture { invocation } => return super::routing::capture(deps, invocation),
})
}
#[cfg(test)]
mod tests;