use super::{Lens, LensContext, LensId, LensOutput};
use forge::budget::estimator::TokenEstimator;
pub struct NarrowLens;
impl Lens for NarrowLens {
fn id(&self) -> LensId {
LensId::Narrow
}
fn apply(&self, input: &str, ctx: &LensContext) -> LensOutput {
let tokens_before = TokenEstimator::count_nonblocking(input);
let budget = ctx.budget.remaining().min(ctx.budget.limit);
if tokens_before <= budget {
return LensOutput {
content: input.to_string(),
tokens_before,
tokens_after: tokens_before,
applied: vec!["narrow".into()],
};
}
let lines: Vec<&str> = input.lines().collect();
if lines.is_empty() {
return LensOutput::passthrough(input);
}
let ratio = budget as f64 / tokens_before as f64;
let target_lines = ((lines.len() as f64 * ratio) as usize).max(10);
let head = (target_lines * 6 / 10).max(5);
let tail = (target_lines * 4 / 10).max(5);
let content = if lines.len() <= head + tail {
lines.join("\n")
} else {
let head_lines = &lines[..head];
let tail_lines = &lines[lines.len() - tail..];
let skipped = lines.len() - head - tail;
format!(
"{}\n... [{skipped} lines omitted] ...\n{}",
head_lines.join("\n"),
tail_lines.join("\n")
)
};
let tokens_after = TokenEstimator::count_nonblocking(&content);
LensOutput {
content,
tokens_before,
tokens_after,
applied: vec!["narrow".into()],
}
}
}