supercode-frontend-tui 0.4.8

Attachable terminal frontend primitives for Supercode SDK runtimes.
Documentation
//! Safe, bounded projections of runtime-owned values for human terminals.

#[cfg(test)]
use serde_json::Value;

/// Remove terminal control protocols and non-printing control characters.
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
}

/// Sanitize and cap display text by Unicode scalar count.
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
}

/// Sanitize protocol-owned labels and collapse line-breaking whitespace so a
/// name cannot escape the header/list row that owns it.
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)
}

/// Produce a bounded semantic description without serializing an opaque
/// runtime object into the terminal. Callers retain the exact `Value` in the
/// model/request object for explicit inspection and round-trip behavior.
#[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"
        );
    }
}