use crate::events::ServerEvent;
use super::{AggregatedEvent, CompletedToolCall};
struct TurnAccumulator {
item_id: String,
text: String,
audio_transcript: String,
tool_calls: Vec<CompletedToolCall>,
}
impl TurnAccumulator {
fn new() -> Self {
Self {
item_id: String::new(),
text: String::new(),
audio_transcript: String::new(),
tool_calls: Vec::new(),
}
}
}
pub struct TranscriptAggregator {
current_turn: Option<TurnAccumulator>,
}
impl TranscriptAggregator {
pub fn new() -> Self {
Self { current_turn: None }
}
pub fn process(&mut self, event: &ServerEvent) -> Option<AggregatedEvent> {
match event {
ServerEvent::ResponseCreated { .. } => {
let interrupted = self.finalize_current(true);
self.current_turn = Some(TurnAccumulator::new());
interrupted
}
ServerEvent::TextDelta { delta, item_id, .. } => {
if let Some(ref mut turn) = self.current_turn {
turn.item_id = item_id.clone();
turn.text.push_str(delta);
}
None
}
ServerEvent::TranscriptDelta { delta, item_id, .. } => {
if let Some(ref mut turn) = self.current_turn {
turn.item_id = item_id.clone();
turn.audio_transcript.push_str(delta);
}
None
}
ServerEvent::ResponseDone { .. } => self.finalize_current(false),
_ => None,
}
}
fn finalize_current(&mut self, interrupted: bool) -> Option<AggregatedEvent> {
self.current_turn.take().map(|turn| AggregatedEvent::TurnComplete {
text: turn.text,
audio_transcript: turn.audio_transcript,
tool_calls: turn.tool_calls,
item_id: turn.item_id,
interrupted,
})
}
pub fn record_tool_call(&mut self, call: CompletedToolCall) {
if let Some(ref mut turn) = self.current_turn {
turn.tool_calls.push(call);
}
}
pub fn process_user_transcript(&mut self, transcript: &str) -> AggregatedEvent {
AggregatedEvent::UserUtteranceComplete { transcript: transcript.to_string() }
}
}
impl Default for TranscriptAggregator {
fn default() -> Self {
Self::new()
}
}