1mod tee;
7
8use std::collections::VecDeque;
9use std::fmt;
10use std::future::Future;
11use std::pin::Pin;
12use std::sync::Arc;
13use std::task::Context;
14use std::task::Poll;
15
16use ferrin_spec::BoxStream;
17use ferrin_spec::JsonValue;
18use ferrin_spec::PartId;
19use ferrin_spec::error::ProviderError;
20use ferrin_spec::error::TypeValidationError;
21use futures_core::Stream;
22use futures_util::FutureExt;
23use futures_util::StreamExt;
24use futures_util::stream;
25use serde::de::DeserializeOwned;
26use tokio::sync::oneshot;
27
28use super::StreamEvent;
29use crate::error::Error;
30use crate::generate_text::GenerateTextResult;
31use crate::output::ArrayElements;
32use crate::output::OutputHandler;
33use crate::output::PartialOutput;
34
35pub type EventStream = BoxStream<'static, StreamEvent>;
37
38pub struct Completion<O> {
45 receiver: oneshot::Receiver<Result<GenerateTextResult<O>, Error>>,
46 driver: Option<EventStream>,
47}
48
49impl<O> Completion<O> {
50 pub(crate) fn new(receiver: oneshot::Receiver<Result<GenerateTextResult<O>, Error>>) -> Self {
51 Self {
52 receiver,
53 driver: None,
54 }
55 }
56
57 fn driving(mut self, driver: EventStream) -> Self {
58 self.driver = Some(driver);
59 self
60 }
61}
62
63impl<O> Future for Completion<O> {
64 type Output = Result<GenerateTextResult<O>, Error>;
65
66 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
67 for _ in 0..64 {
70 match Pin::new(&mut self.receiver).poll(cx) {
71 Poll::Ready(Ok(result)) => {
72 self.driver = None;
73 return Poll::Ready(result);
74 }
75 Poll::Ready(Err(_)) => {
76 self.driver = None;
77 return Poll::Ready(Err(Error::Cancelled));
78 }
79 Poll::Pending => {}
80 }
81 let Some(driver) = self.driver.as_mut() else {
82 return Poll::Pending;
83 };
84 match driver.as_mut().poll_next(cx) {
85 Poll::Ready(Some(_)) => {}
86 Poll::Ready(None) => {
87 self.driver = None;
88 }
89 Poll::Pending => return Poll::Pending,
90 }
91 }
92 cx.waker().wake_by_ref();
93 Poll::Pending
94 }
95}
96
97impl<O> fmt::Debug for Completion<O> {
98 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
99 f.write_str("Completion(..)")
100 }
101}
102
103pub struct StreamTextResult<O> {
110 pub(crate) call_id: String,
111 pub(crate) events: EventStream,
112 pub(crate) completion: Completion<O>,
113 pub(crate) output: Arc<dyn OutputHandler<O>>,
114}
115
116impl<O> fmt::Debug for StreamTextResult<O> {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.debug_struct("StreamTextResult")
119 .field("call_id", &self.call_id)
120 .finish_non_exhaustive()
121 }
122}
123
124impl<O> StreamTextResult<O> {
125 #[must_use]
127 pub fn call_id(&self) -> &str {
128 &self.call_id
129 }
130
131 #[must_use]
133 pub fn split(self) -> (EventStream, Completion<O>) {
134 let (events, driver) = tee::tee(self.events);
135 (events, self.completion.driving(driver))
136 }
137
138 #[must_use]
143 pub fn full_stream(&mut self) -> EventStream {
144 let current = std::mem::replace(&mut self.events, Box::pin(stream::empty()));
145 let (view, retained) = tee::tee(current);
146 self.events = retained;
147 view
148 }
149
150 #[must_use]
152 pub fn into_completion(self) -> Completion<O> {
153 self.completion.driving(self.events)
154 }
155
156 pub async fn final_result(self) -> Result<GenerateTextResult<O>, Error> {
163 self.into_completion().await
164 }
165
166 pub fn text_view(&mut self) -> impl Stream<Item = String> + Send + use<O> {
170 self.full_stream().filter_map(|event| async move {
171 match event {
172 StreamEvent::TextDelta { text, .. } => Some(text),
173 _ => None,
174 }
175 })
176 }
177
178 pub fn events(&mut self) -> &mut EventStream {
180 &mut self.events
181 }
182
183 pub async fn consume(self) -> Result<GenerateTextResult<O>, Error> {
189 self.final_result().await
190 }
191}
192
193impl<O: Send + Sync + 'static> StreamTextResult<O> {
194 pub fn into_shared_completion(
200 self,
201 ) -> impl Future<Output = Arc<Result<GenerateTextResult<O>, Error>>> + Clone + Send {
202 self.into_completion().map(Arc::new).boxed().shared()
203 }
204}
205
206impl<O: Send + 'static> StreamTextResult<O> {
207 pub fn text_stream(self) -> impl Stream<Item = Result<String, Error>> + Send {
210 stream::unfold(Some((self.events, self.completion)), |state| async move {
211 let (mut events, completion) = state?;
212 loop {
213 match events.next().await {
214 Some(StreamEvent::TextDelta { text, .. }) => {
215 return Some((Ok(text), Some((events, completion))));
216 }
217 Some(_) => {}
218 None => {
219 return match completion.await {
220 Ok(_) => None,
221 Err(error) => Some((Err(error), None)),
222 };
223 }
224 }
225 }
226 })
227 }
228
229 pub fn partial_output_stream(self) -> impl Stream<Item = PartialOutput<O>> + Send {
235 partial_stream(self.events, self.output)
236 }
237
238 pub fn partial_output_view(&mut self) -> impl Stream<Item = PartialOutput<O>> + Send + use<O> {
243 partial_stream(self.full_stream(), self.output.clone())
244 }
245}
246
247fn partial_stream<O: Send + 'static>(
248 events: EventStream,
249 handler: Arc<dyn OutputHandler<O>>,
250) -> impl Stream<Item = PartialOutput<O>> + Send {
251 let state = PartialState {
252 events,
253 handler,
254 first_text: None,
255 text: String::new(),
256 last: None,
257 };
258 stream::unfold(Some(state), |state| async move {
259 let mut state = state?;
260 loop {
261 let event = state.events.next().await?;
262 if let Some(output) = state.handle(&event) {
263 return Some((output, Some(state)));
264 }
265 }
266 })
267}
268
269struct PartialState<O> {
270 events: EventStream,
271 handler: Arc<dyn OutputHandler<O>>,
272 first_text: Option<PartId>,
273 text: String,
274 last: Option<JsonValue>,
275}
276
277impl<O: 'static> PartialState<O> {
278 fn reset(&mut self) {
279 self.first_text = None;
280 self.text.clear();
281 self.last = None;
282 }
283
284 fn handle(&mut self, event: &StreamEvent) -> Option<PartialOutput<O>> {
285 match event {
286 StreamEvent::RetryAttempt { .. } => {
287 self.reset();
288 None
289 }
290 StreamEvent::TextStart { id, .. } => {
291 if self.first_text.is_none() {
292 self.first_text = Some(id.clone());
293 }
294 None
295 }
296 StreamEvent::TextDelta { id, text, .. } => {
297 if self.first_text.as_ref() != Some(id) || text.is_empty() {
298 return None;
299 }
300 self.text.push_str(text);
301 let value = self.handler.parse_partial(&self.text)?;
302 if self.last.as_ref() == Some(&value) {
303 return None;
304 }
305 self.last = Some(value.clone());
306 let typed = self.handler.typed_partial(&value);
307 Some(PartialOutput { value, typed })
308 }
309 _ => None,
310 }
311 }
312}
313
314impl<O> StreamTextResult<O>
315where
316 O: ArrayElements + IntoIterator<Item = <O as ArrayElements>::Element> + Send + 'static,
317 O::Element: DeserializeOwned + Send,
318{
319 pub fn element_stream(self) -> impl Stream<Item = Result<O::Element, Error>> + Send {
322 elements(self.events, Some(self.completion), self.output)
323 }
324
325 pub fn element_view(
330 &mut self,
331 ) -> impl Stream<Item = Result<O::Element, Error>> + Send + use<O> {
332 elements(self.full_stream(), None, self.output.clone())
333 }
334}
335
336fn elements<O>(
337 events: EventStream,
338 completion: Option<Completion<O>>,
339 handler: Arc<dyn OutputHandler<O>>,
340) -> impl Stream<Item = Result<O::Element, Error>> + Send
341where
342 O: ArrayElements + IntoIterator<Item = <O as ArrayElements>::Element> + Send + 'static,
343 O::Element: DeserializeOwned + Send,
344{
345 let state = ElementState {
346 events,
347 completion,
348 handler,
349 first_text: None,
350 text: String::new(),
351 published: 0,
352 pending: VecDeque::new(),
353 failed: false,
354 };
355 stream::unfold(Some(state), |state| async move {
356 let mut state = state?;
357 loop {
358 if let Some(item) = state.pending.pop_front() {
359 let next = if state.failed && state.pending.is_empty() {
360 None
361 } else {
362 Some(state)
363 };
364 return Some((item, next));
365 }
366 match state.events.next().await {
367 Some(event) => state.handle(&event),
368 None => {
369 let completion = state.completion.take()?;
370 return match completion.await {
371 Ok(_) => None,
372 Err(error) => Some((Err(error), None)),
373 };
374 }
375 }
376 }
377 })
378}
379
380struct ElementState<O: ArrayElements> {
381 events: EventStream,
382 completion: Option<Completion<O>>,
383 handler: Arc<dyn OutputHandler<O>>,
384 first_text: Option<PartId>,
385 text: String,
386 published: usize,
387 pending: VecDeque<Result<O::Element, Error>>,
388 failed: bool,
389}
390
391impl<O> ElementState<O>
392where
393 O: ArrayElements + IntoIterator<Item = <O as ArrayElements>::Element> + 'static,
394 O::Element: DeserializeOwned,
395{
396 fn handle(&mut self, event: &StreamEvent) {
397 match event {
398 StreamEvent::RetryAttempt { .. } => {
399 self.first_text = None;
400 self.text.clear();
401 }
404 StreamEvent::TextStart { id, .. } => {
405 if self.first_text.is_none() {
406 self.first_text = Some(id.clone());
407 }
408 }
409 StreamEvent::TextDelta { id, text, .. } => {
410 if self.first_text.as_ref() != Some(id) || text.is_empty() {
411 return;
412 }
413 self.text.push_str(text);
414 let elements: Vec<Result<O::Element, Error>> =
415 if let Some(typed) = self.handler.parse_typed_elements(&self.text) {
416 typed.into_iter().map(Ok).collect()
417 } else if let Some(raw) = self.handler.parse_elements(&self.text) {
418 raw.into_iter()
419 .map(|value| serde_json::from_value(value).map_err(Error::other))
420 .collect()
421 } else {
422 return;
423 };
424 for element in elements.into_iter().skip(self.published) {
425 if let Some(max) = self.handler.max_elements()
426 && self.published >= max
427 {
428 let value = self
429 .handler
430 .parse_partial(&self.text)
431 .unwrap_or(JsonValue::Null);
432 let error = TypeValidationError::new(
433 value,
434 std::io::Error::other(format!(
435 "elements array must contain at most {max} items"
436 )),
437 );
438 self.pending
439 .push_back(Err(Error::from(ProviderError::from(error))));
440 self.failed = true;
441 break;
442 }
443 self.published += 1;
444 self.pending.push_back(element);
445 }
446 }
447 _ => {}
448 }
449 }
450}