use crate::ui_state::UiState;
use super::dispatch::Deps;
use super::reply::Reply;
use super::{Query, config, help};
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 xdg = deps.world.balls_layout();
let attempts = crate::workdiff::read(snap, ws, &entries, &xdg);
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);
let xdg = deps.world.balls_layout();
Reply::Science(crate::science::project(
snap,
ws,
&entries,
&xdg,
&deps.balls_state_root,
))
}
Query::Transcript { .. } => Reply::Transcript(inspector::transcript(snap, ws, agent)),
Query::Follow { .. } => {
Reply::Follow(inspector::live_tail(snap, ws, agent).unwrap_or_default())
}
Query::Steps { .. } => Reply::Steps(inspector::steps(snap, ws, agent)),
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);
let tx = inspector::transcript(snap, ws, agent);
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);
Reply::Ops(snap.ops.iter().skip(skip).cloned().collect())
}
Query::Config(read) => {
return match read {
config::Read::File { file } => config::read(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)),
};
}
Query::Clients { workspace } => Reply::Clients(crate::registry::roster::roster(
&deps.state_root,
&deps.caller.presence,
workspace,
)),
Query::Invocations => return super::routing::invocations(deps),
Query::Capture { invocation } => return super::routing::capture(deps, invocation),
})
}
#[cfg(test)]
mod tests;