use crate::event::{AISdkEvent, FinishReason, MessageMetadata, ProviderMetadata};
use uuid::Uuid;
#[derive(Debug)]
pub struct AISdkStreamBuilder {
message_id: String,
text_id: Option<String>,
reasoning_id: Option<String>,
}
impl AISdkStreamBuilder {
pub fn new() -> Self {
Self {
message_id: Uuid::new_v4().to_string(),
text_id: None,
reasoning_id: None,
}
}
pub fn start(&self) -> AISdkEvent {
AISdkEvent::Start {
message_id: self.message_id.clone(),
message_metadata: None,
provider_metadata: None,
}
}
pub fn start_with_metadata(
&self,
message_metadata: Option<MessageMetadata>,
provider_metadata: Option<ProviderMetadata>,
) -> AISdkEvent {
AISdkEvent::Start {
message_id: self.message_id.clone(),
message_metadata,
provider_metadata,
}
}
pub fn text_start(&mut self) -> Option<AISdkEvent> {
self.text_start_with_metadata(None)
}
pub fn text_start_with_metadata(
&mut self,
provider_metadata: Option<ProviderMetadata>,
) -> Option<AISdkEvent> {
if self.text_id.is_some() {
return None;
}
let id = Uuid::new_v4().to_string();
self.text_id = Some(id.clone());
Some(AISdkEvent::TextStart { id, provider_metadata })
}
pub fn text_delta(&self, delta: impl Into<String>) -> Option<AISdkEvent> {
self.text_delta_with_metadata(delta, None)
}
pub fn text_delta_with_metadata(
&self,
delta: impl Into<String>,
provider_metadata: Option<ProviderMetadata>,
) -> Option<AISdkEvent> {
self.text_id.clone().map(|id| AISdkEvent::TextDelta {
id,
delta: delta.into(),
provider_metadata,
})
}
pub fn text_end(&mut self) -> Option<AISdkEvent> {
self.text_end_with_metadata(None)
}
pub fn text_end_with_metadata(
&mut self,
provider_metadata: Option<ProviderMetadata>,
) -> Option<AISdkEvent> {
self.text_id.take().map(|id| AISdkEvent::TextEnd { id, provider_metadata })
}
pub fn reasoning_start(&mut self, _reasoning_id: Option<String>) -> AISdkEvent {
self.reasoning_start_with_metadata(None)
}
pub fn reasoning_start_with_metadata(
&mut self,
provider_metadata: Option<ProviderMetadata>,
) -> AISdkEvent {
let id = Uuid::new_v4().to_string();
self.reasoning_id = Some(id.clone());
AISdkEvent::ReasoningStart { id, provider_metadata }
}
pub fn reasoning_delta(
&self,
delta: impl Into<String>,
reasoning_id: Option<String>,
) -> Option<AISdkEvent> {
self.reasoning_delta_with_metadata(delta, reasoning_id, None)
}
pub fn reasoning_delta_with_metadata(
&self,
delta: impl Into<String>,
reasoning_id: Option<String>,
provider_metadata: Option<ProviderMetadata>,
) -> Option<AISdkEvent> {
reasoning_id
.or_else(|| self.reasoning_id.as_ref().map(|id| id.to_string()))
.map(|id| AISdkEvent::ReasoningDelta {
id,
delta: delta.into(),
provider_metadata,
})
}
pub fn reasoning_end(&mut self) -> Option<AISdkEvent> {
self.reasoning_end_with_metadata(None)
}
pub fn reasoning_end_with_metadata(
&mut self,
provider_metadata: Option<ProviderMetadata>,
) -> Option<AISdkEvent> {
self.reasoning_id
.take()
.map(|id| AISdkEvent::ReasoningEnd { id, provider_metadata })
}
pub fn finish(&self) -> AISdkEvent {
AISdkEvent::Finish {
finish_reason: None,
message_metadata: None,
}
}
pub fn finish_with_reason(&self, finish_reason: FinishReason) -> AISdkEvent {
AISdkEvent::Finish {
finish_reason: Some(finish_reason),
message_metadata: None,
}
}
pub fn finish_with_metadata(
&self,
finish_reason: Option<FinishReason>,
message_metadata: Option<MessageMetadata>,
) -> AISdkEvent {
AISdkEvent::Finish {
finish_reason,
message_metadata,
}
}
pub fn done(&self) -> AISdkEvent {
AISdkEvent::Done
}
}
impl Default for AISdkStreamBuilder {
fn default() -> Self {
Self::new()
}
}