oy-cli 0.10.0

Local AI coding CLI for inspecting, editing, running commands, and auditing repositories
Documentation
#[derive(Debug, Default)]
pub(crate) struct SseDecoder {
    buffer: String,
}

impl SseDecoder {
    pub(crate) fn push_chunk(&mut self, chunk: &[u8]) -> Vec<String> {
        self.buffer.push_str(&String::from_utf8_lossy(chunk));
        let mut events = Vec::new();
        while let Some(index) = self.buffer.find("\n\n") {
            let frame = self.buffer[..index].to_string();
            self.buffer.drain(..index + 2);
            events.extend(sse_data_lines(&frame));
        }
        events
    }

    pub(crate) fn finish(&mut self) -> Vec<String> {
        if self.buffer.trim().is_empty() {
            self.buffer.clear();
            return Vec::new();
        }
        let frame = std::mem::take(&mut self.buffer);
        sse_data_lines(&frame)
    }
}

fn sse_data_lines(frame: &str) -> Vec<String> {
    let mut items = Vec::new();
    for line in frame.lines() {
        let line = line.trim_end_matches('\r');
        let Some(data) = line.strip_prefix("data:") else {
            continue;
        };
        let data = data.trim_start();
        if !data.trim().is_empty() && data != "[DONE]" {
            items.push(data.to_string());
        }
    }
    items
}

#[cfg(test)]
#[path = "../test/framing.rs"]
mod tests;