#[cfg(test)]
use serde_json::Value;
pub(crate) fn sanitize_terminal_text(input: &str) -> String {
#[derive(Clone, Copy)]
enum State {
Text,
Escape,
Csi,
Osc,
OscEscape,
}
let mut state = State::Text;
let mut out = String::with_capacity(input.len());
for ch in input.chars() {
state = match state {
State::Text if ch == '\u{1b}' => State::Escape,
State::Text => {
if ch == '\n' || ch == '\t' || !ch.is_control() {
out.push(ch);
}
State::Text
}
State::Escape if ch == '[' => State::Csi,
State::Escape if ch == ']' => State::Osc,
State::Escape => State::Text,
State::Csi if ('@'..='~').contains(&ch) => State::Text,
State::Csi => State::Csi,
State::Osc if ch == '\u{7}' => State::Text,
State::Osc if ch == '\u{1b}' => State::OscEscape,
State::Osc => State::Osc,
State::OscEscape if ch == '\\' => State::Text,
State::OscEscape if ch == '\u{1b}' => State::OscEscape,
State::OscEscape => State::Osc,
};
}
out
}
pub(crate) fn bounded_terminal_text(input: &str, limit: usize) -> String {
let sanitized = sanitize_terminal_text(input);
if sanitized.chars().count() <= limit {
return sanitized;
}
let mut preview = sanitized
.chars()
.take(limit.saturating_sub(1))
.collect::<String>();
preview.push('…');
preview
}
pub(crate) fn bounded_terminal_metadata(input: &str, limit: usize) -> String {
let flattened = sanitize_terminal_text(input)
.chars()
.map(|character| match character {
'\n' | '\t' => ' ',
character => character,
})
.collect::<String>();
bounded_terminal_text(&flattened, limit)
}
#[cfg(test)]
pub(crate) fn semantic_value_summary(value: &Value, label: &str, limit: usize) -> String {
supercode_frontend_model::semantic_value_summary(value, label, limit)
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
#[test]
fn strips_color_title_and_hyperlink_controls() {
let input =
"\x1b[31mred\x1b[0m \x1b]0;title\x07ok \x1b]8;;https://example.com\x07link\x1b]8;;\x07";
assert_eq!(sanitize_terminal_text(input), "red ok link");
}
#[test]
fn semantic_summary_never_serializes_large_nested_payload() {
let value = json!({
"nested": {"secret": "x".repeat(10_000)},
"\u{1b}]0;owned\u{7}field": true,
});
let summary = semantic_value_summary(&value, "Approval request", 256);
assert!(summary.len() < 256, "{summary}");
assert!(!summary.contains("secret"), "{summary}");
assert!(!summary.contains('\u{1b}'), "{summary:?}");
assert!(
summary.starts_with("Approval request (fields:"),
"{summary}"
);
}
#[test]
fn metadata_cannot_escape_its_display_row() {
assert_eq!(
bounded_terminal_metadata("tool\n\u{1b}]0;owned\u{7}name\tfield", 64),
"tool name field"
);
}
}