Skip to main content

oxi_ai/
partial_response.rs

1//! Partial response accumulator for stream recovery.
2
3/// Partial response accumulator.
4///
5/// Collects streamed text and thinking deltas so they can be recovered
6/// if the stream terminates unexpectedly.
7#[derive(Debug, Default)]
8pub struct PartialResponse {
9    /// Accumulated response text.
10    text: String,
11    /// Accumulated thinking / reasoning text.
12    thinking: String,
13    /// Whether any thinking content has been received.
14    has_thinking: bool,
15}
16
17impl PartialResponse {
18    /// Create a new empty partial response.
19    pub fn new() -> Self {
20        Self::default()
21    }
22
23    /// Append a text delta to the accumulated response.
24    pub fn push_text(&mut self, delta: &str) {
25        self.text.push_str(delta);
26    }
27
28    /// Append a thinking delta to the accumulated reasoning.
29    pub fn push_thinking(&mut self, delta: &str) {
30        self.has_thinking = true;
31        self.thinking.push_str(delta);
32    }
33
34    /// Take ownership of the accumulated text, leaving an empty string behind.
35    pub fn take_text(&mut self) -> String {
36        std::mem::take(&mut self.text)
37    }
38
39    /// Access the accumulated response text.
40    pub fn text(&self) -> &str {
41        &self.text
42    }
43
44    /// Access the accumulated thinking / reasoning text.
45    pub fn thinking(&self) -> &str {
46        &self.thinking
47    }
48
49    /// Returns `true` if any thinking content has been received.
50    pub fn has_thinking(&self) -> bool {
51        self.has_thinking
52    }
53
54    /// Returns `true` if no text or thinking has been accumulated.
55    pub fn is_empty(&self) -> bool {
56        self.text.is_empty() && self.thinking.is_empty()
57    }
58
59    /// Clear all accumulated content.
60    pub fn clear(&mut self) {
61        self.text.clear();
62        self.thinking.clear();
63        self.has_thinking = false;
64    }
65}