use std::path::Path;
use std::sync::Arc;
use crate::AppModel;
use crate::budgets::{Scope, bills, total};
use crate::config_edit::branch::governing_config;
use crate::files_view::{self, FilesView, Preview};
use crate::git_tree::{Agent, children_of};
use crate::nav::convs::display_name_of;
use crate::rail::{self, ChildInput, Pin, Rail};
use crate::steps_view::StepsView;
use crate::transcript::Transcript;
use super::super::InspectorState;
pub fn build(
model: &AppModel,
inspector: &mut InspectorState,
ws: &Path,
agent_id: &str,
speaker: &str,
steps: &StepsView,
tx: &Transcript,
) -> Rail {
let agents = model
.focused_tree()
.map(|tree| tree.agents.clone())
.unwrap_or_default();
let parent_commits = agents
.iter()
.find(|a| a.agent_id == agent_id)
.map(|a| a.steps.clone())
.unwrap_or_default();
let snap = Arc::clone(model.derivation());
inspector
.rail_memo
.read(&snap, (ws.to_path_buf(), agent_id.to_owned()), &mut || {
let children: Vec<ChildInput> = children_of(&agents, agent_id)
.into_iter()
.filter_map(|index| agents.get(index))
.map(|child| child_input(ws, &agents, child))
.collect();
rail::build(speaker, &parent_commits, steps, tx, &children)
})
.clone()
}
fn child_input(ws: &Path, agents: &[Agent], child: &Agent) -> ChildInput {
ChildInput {
agent_id: child.agent_id.clone(),
name: display_name_of(agents, &child.agent_id),
state: child.state,
streaming_text: child.stream.text.clone(),
commits: child.steps.clone(),
tokens: total(&bills(ws, &Scope::Agent(child.agent_id.clone()))).total_tokens(),
config_label: governing_config(ws, &child.tip_oid)
.ok()
.and_then(|gov| gov.branch_name_if_tip_of_one),
}
}
pub fn pinned(rail: &Rail, notch_sel: Option<usize>) -> Option<Pin> {
rail::pin(rail, notch_sel)
}
pub fn transcript(live: &Arc<Transcript>, pin: Option<&Pin>) -> Arc<Transcript> {
match pin {
None => Arc::clone(live),
Some(pin) => Arc::new(rail::transcript_as_of(live, pin.cut)),
}
}
pub fn files(
model: &AppModel,
inspector: &mut InspectorState,
ws: &Path,
agent_id: &str,
pin: Option<&Pin>,
) -> FilesView {
let commit = pin.map(|p| p.commit.clone());
let snap = Arc::clone(model.derivation());
let (root, id) = (ws.to_path_buf(), agent_id.to_owned());
inspector
.files_memo
.read(&snap, (root, id, commit.clone()), &mut || match &commit {
Some(oid) => rail::files_at(ws, oid),
None => files_view::build(ws, agent_id),
})
.clone()
}
pub fn preview(ws: &Path, agent_id: &str, rel_path: &str, pin: Option<&Pin>) -> Preview {
match pin {
Some(pin) => rail::preview_at(ws, &pin.commit, rel_path),
None => files_view::preview(&files_view::agent_worktree(ws, agent_id).join(rel_path)),
}
}
pub fn governing(
ws: &Path,
tip: &str,
pin: Option<&Pin>,
) -> Option<crate::config_edit::branch::GoverningConfig> {
let at = pin.map_or(tip, |pin| pin.commit.as_str());
governing_config(ws, at).ok()
}