ras-agent 2.0.0

Agent step loop, history, plan, rerun orchestration
Documentation
use indexmap::IndexMap;
use regex::Regex;

const MIN_URL_LEN: usize = 80;

#[derive(Debug, Default)]
pub struct UrlShortener {
    map: IndexMap<String, String>,
}

impl UrlShortener {
    #[must_use]
    pub fn new() -> Self {
        Self::default()
    }

    pub fn shorten(&mut self, text: &str) -> String {
        let Ok(re) = Regex::new(r#"https?://[^\s"'<>]+"#) else {
            return text.to_string();
        };
        let mut next_id = self.map.len();
        let mut result = String::with_capacity(text.len());
        let mut last_end = 0;
        for m in re.find_iter(text) {
            result.push_str(&text[last_end..m.start()]);
            let original = m.as_str();
            if original.len() < MIN_URL_LEN {
                result.push_str(original);
            } else if let Some(short) = self.lookup_existing(original) {
                result.push_str(&short);
            } else {
                let key = format!("ras://url/{next_id}");
                self.map.insert(key.clone(), original.to_string());
                result.push_str(&key);
                next_id += 1;
            }
            last_end = m.end();
        }
        result.push_str(&text[last_end..]);
        result
    }

    pub fn restore(&self, text: &str) -> String {
        let mut out = text.to_string();
        for (short, full) in &self.map {
            out = out.replace(short, full);
        }
        out
    }

    fn lookup_existing(&self, original: &str) -> Option<String> {
        self.map
            .iter()
            .find_map(|(k, v)| (v == original).then(|| k.clone()))
    }
}