use super::*;
pub(crate) fn unit_glyph(role: Role) -> &'static str {
match role {
Role::User => "▽",
Role::Assistant => "△",
}
}
pub(crate) fn unit_header_line(unit: &TurnUnit) -> String {
let dup = if unit.also_in_summary {
" (also in summary)"
} else {
""
};
let locator = if unit.from_sidecar {
"(elicitation sidecar)".to_string()
} else {
format!("L{}", unit.line_no)
};
let role_field = match &unit.inbound {
Some(ic) => format!("{} {} ⇨ self", ic.class.path(), ic.from),
None => unit.role.label().to_uppercase(),
};
format!(
"{} {locator} {role_field} ({}){dup}",
unit_glyph(unit.role),
format_timestamp(unit.ts_utc.as_deref())
)
}
pub(crate) fn unit_cost(unit: &TurnUnit) -> usize {
let header_chars = unit_header_line(unit).chars().count() + NEWLINE_COST;
let body_chars = render_unit_body(unit, None).body.chars().count() + NEWLINE_COST;
header_chars + body_chars
}
pub(crate) fn marker_cost(tool_calls: usize) -> usize {
if tool_calls == 0 {
0
} else {
format!(" [{tool_calls} tool calls]").chars().count() + NEWLINE_COST
}
}
pub(crate) fn image_marker_line(ids: &[String]) -> String {
let noun = if ids.len() == 1 { "image" } else { "images" };
format!(" [{} {}: {}]", ids.len(), noun, ids.join(", "))
}
pub(crate) fn image_marker_cost(ids: &[String]) -> usize {
if ids.is_empty() {
0
} else {
image_marker_line(ids).chars().count() + NEWLINE_COST
}
}
pub(crate) fn boundary_banner_line(line_no: usize, mode: Option<SummarizeMode>) -> String {
let tag = match mode {
Some(SummarizeMode::FromHere | SummarizeMode::UpToHere) => mode
.and_then(SummarizeMode::direction)
.map(|d| format!(" · summarize {d}"))
.unwrap_or_default(),
_ => String::new(),
};
format!(
"{0} compaction boundary · summary at L{1}{2} · (turns below predate it) {0}",
"══", line_no, tag
)
}
pub(crate) fn banner_cost(line_no: usize, mode: Option<SummarizeMode>) -> usize {
boundary_banner_line(line_no, mode).chars().count() + NEWLINE_COST
}
pub(crate) fn cumulative_banner_cost(summaries: &[SummaryInfo], depth: usize) -> usize {
if depth == 0 {
return 0;
}
let mut by_rank: Vec<(usize, Option<SummarizeMode>)> =
summaries.iter().map(|s| (s.line_no, s.mode)).collect();
by_rank.sort_unstable_by(|a, b| b.0.cmp(&a.0));
by_rank
.into_iter()
.take(depth)
.map(|(line_no, mode)| banner_cost(line_no, mode))
.sum()
}
pub(crate) fn doc_header_block_max_chars(sr: &ScanResult, budget: usize) -> usize {
let turns = sr.turns.len();
let summaries = sr.summaries.len();
let max_agent_units = sr.turns.iter().map(|t| t.agents.len()).sum::<usize>();
let max_line = sr
.summaries
.iter()
.map(|s| s.line_no)
.chain(sr.turns.iter().map(turn_latest_line))
.max()
.unwrap_or(0);
let line_session = format!("SESSION {}", sr.session_id);
let line_budget = format!(
" budget {} chars · round-trip-fraction {:.2} · spanned {} of {} compaction boundaries in scope",
budget, 0.0_f64, summaries, summaries
);
let has_automation = sr.turns.iter().any(|t| t.is_automation);
let line_selected = if has_automation {
format!(
" selected {} user ({} automation triggers) + {} assistant units across {} turns · {} / {} chars used",
turns, turns, max_agent_units, turns, budget, budget
)
} else {
format!(
" selected {} user + {} assistant units across {} turns · {} / {} chars used",
turns, max_agent_units, turns, budget, budget
)
};
let line_dedup = format!(
" dedup: {} units also present in summary L{} (demoted, flagged)",
2 * turns,
max_line
);
let line_rule = format!(" {}", "─".repeat(60));
[
line_session,
line_budget,
line_selected,
line_dedup,
line_rule,
]
.iter()
.map(|l| l.chars().count() + NEWLINE_COST)
.sum()
}
pub(crate) fn assistant_lane_cost(turn: &TurnSlice, cfg: &RichnessCfg) -> usize {
select_agent_messages(turn, cfg)
.iter()
.map(|r| match r {
AgentRender::Kept(a) => unit_cost(&a.unit),
AgentRender::Placeholder(s) => agent_placeholder_cost(s),
AgentRender::Superseded { msg, by_line } => superseded_cost(msg, *by_line),
})
.sum()
}
pub(crate) fn turn_cost(turn: &TurnSlice, sides: SelSides, cfg: &RichnessCfg) -> usize {
let mut c = 0;
if matches!(sides, SelSides::Both | SelSides::UserOnly) {
if let Some(u) = &turn.user {
c += unit_cost(u);
c += image_marker_cost(&turn.image_ids);
}
}
if matches!(sides, SelSides::Both) {
c += marker_cost(turn.tool_calls);
}
if matches!(sides, SelSides::Both | SelSides::AssistantOnly) {
c += assistant_lane_cost(turn, cfg);
}
c
}