1use futures::Stream;
2use std::pin::Pin;
3use std::task::{Context, Poll};
4use tokio::sync::mpsc;
5
6#[derive(Debug, Clone)]
7pub enum VoiceEvent {
8 SpeechStarted {
9 audio_start_ms: Option<u32>,
10 },
11 SpeechStopped {
12 audio_end_ms: Option<u32>,
13 },
14 AudioDelta {
15 response_id: String,
16 item_id: String,
17 output_index: u32,
18 content_index: u32,
19 pcm: Vec<u8>,
20 },
21 AudioDone {
22 response_id: String,
23 item_id: String,
24 output_index: u32,
25 content_index: u32,
26 },
27 TranscriptDelta {
28 response_id: String,
29 item_id: String,
30 output_index: u32,
31 content_index: u32,
32 delta: String,
33 },
34 TranscriptDone {
35 response_id: String,
36 item_id: String,
37 output_index: u32,
38 content_index: u32,
39 transcript: String,
40 },
41 UserTranscriptDone {
42 item_id: String,
43 content_index: u32,
44 transcript: String,
45 },
46 ResponseCreated {
47 response_id: String,
48 },
49 ResponseDone {
50 response_id: String,
51 },
52 ResponseCancelled {
53 response_id: String,
54 },
55 DecodeError {
56 message: String,
57 },
58}
59
60#[derive(Debug, Clone)]
61pub struct AudioChunk {
62 pub response_id: String,
63 pub item_id: String,
64 pub output_index: u32,
65 pub content_index: u32,
66 pub pcm: Vec<u8>,
67}
68
69#[derive(Debug, Clone)]
70pub struct TranscriptChunk {
71 pub response_id: String,
72 pub item_id: String,
73 pub output_index: u32,
74 pub content_index: u32,
75 pub text: String,
76 pub is_final: bool,
77}
78
79pub struct VoiceEventStream<'a> {
80 rx: &'a mut mpsc::Receiver<VoiceEvent>,
81}
82
83impl<'a> VoiceEventStream<'a> {
84 #[must_use]
85 pub const fn new(rx: &'a mut mpsc::Receiver<VoiceEvent>) -> Self {
86 Self { rx }
87 }
88}
89
90impl Stream for VoiceEventStream<'_> {
91 type Item = VoiceEvent;
92
93 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
94 let this = self.get_mut();
95 Pin::new(&mut this.rx).poll_recv(cx)
96 }
97}