use super::*;
fn unit(role: Role, line_no: usize, text: &str, orig_newlines: usize) -> TurnUnit {
TurnUnit {
line_no,
role,
full_chars: text.chars().count(),
text: text.to_string(),
orig_newlines,
ts_utc: Some("2026-06-07T05:00:00.000Z".to_string()),
also_in_summary: false,
from_sidecar: false,
inbound: None,
}
}
fn agent_msg(line_no: usize, text: &str, tools: usize, failed: usize) -> AgentMsg {
AgentMsg {
unit: unit(Role::Assistant, line_no, text, 0),
pos: AgentPos::Last, preceding_tool_calls: tools,
preceding_failed: failed,
}
}
fn assign_positions(agents: &mut [AgentMsg]) {
let last = agents.len().saturating_sub(1);
for (i, a) in agents.iter_mut().enumerate() {
a.pos = if i == last {
AgentPos::Last
} else if i == 0 {
AgentPos::First
} else {
AgentPos::Middle
};
}
}
fn longest_cfg() -> RichnessCfg {
RichnessCfg::default()
}
fn mk_turn(
turn_index: usize,
user: Option<&str>,
asst: Option<&str>,
tools: usize,
comp: usize,
) -> TurnSlice {
let mut agents: Vec<AgentMsg> = asst
.map(|t| vec![agent_msg(turn_index * 10 + 5, t, 0, 0)])
.unwrap_or_default();
assign_positions(&mut agents);
TurnSlice {
turn_index,
user: user.map(|t| unit(Role::User, turn_index * 10 + 1, t, 0)),
tool_calls: tools,
image_ids: Vec::new(),
agents,
compactions_before: comp,
is_automation: false,
automation: None,
}
}
fn mk_turn_agents(
turn_index: usize,
user: Option<&str>,
agent_texts: &[&str],
comp: usize,
) -> TurnSlice {
let mut agents: Vec<AgentMsg> = agent_texts
.iter()
.enumerate()
.map(|(i, t)| agent_msg(turn_index * 100 + i + 5, t, 1, 0))
.collect();
assign_positions(&mut agents);
TurnSlice {
turn_index,
user: user.map(|t| unit(Role::User, turn_index * 100 + 1, t, 0)),
tool_calls: agents.len(),
image_ids: Vec::new(),
agents,
compactions_before: comp,
is_automation: false,
automation: None,
}
}
fn rec(json: &str) -> Record {
serde_json::from_str(json).expect("valid record")
}
fn rich_cfg() -> RichnessCfg {
RichnessCfg {
mode: AgentMsgMode::Rich,
..RichnessCfg::default()
}
}
fn scan_with_turns(turns: Vec<TurnSlice>, summaries: Vec<SummaryInfo>) -> ScanResult {
ScanResult {
session_id: "s".to_string(),
is_subagent: false,
parent_session_id: "s".to_string(),
turns,
summaries,
skipped_lines: 0,
}
}
fn summary(line_no: usize, fps: Vec<&str>, body_chars: usize) -> SummaryInfo {
SummaryInfo {
line_no,
fingerprints: fps.into_iter().map(fingerprint).collect(),
body_chars,
}
}
fn cfg() -> RichnessCfg {
RichnessCfg {
mode: AgentMsgMode::EotOnly,
..RichnessCfg::default()
}
}
mod automation;
mod boundaries;
mod build;
mod cost;
mod dedup;
mod planning;
mod render_caps;
mod richness;
mod scan;
mod select;
fn body_chars(tag: &str, n: usize) -> String {
let suffix = format!(" {tag}");
let fill = n.saturating_sub(suffix.chars().count());
let mut s = "x".repeat(fill);
s.push_str(&suffix);
s
}