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}