use std::marker::PhantomData;
use entelix_core::ir::{ContentPart, Message};
use entelix_core::{Error, ExecutionContext, Result};
use serde::de::DeserializeOwned;
use crate::runnable::Runnable;
pub struct JsonOutputParser<T> {
_phantom: PhantomData<fn() -> T>,
}
impl<T> JsonOutputParser<T> {
pub const fn new() -> Self {
Self {
_phantom: PhantomData,
}
}
}
impl<T> Default for JsonOutputParser<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> Clone for JsonOutputParser<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for JsonOutputParser<T> {}
#[async_trait::async_trait]
impl<T> Runnable<Message, T> for JsonOutputParser<T>
where
T: DeserializeOwned + Send + 'static,
{
async fn invoke(&self, input: Message, _ctx: &ExecutionContext) -> Result<T> {
let mut text = String::new();
for part in &input.content {
if let ContentPart::Text { text: t, .. } = part {
text.push_str(t);
}
}
if text.is_empty() {
return Err(Error::invalid_request(
"JsonOutputParser: message contains no text parts",
));
}
Ok(serde_json::from_str(&text)?)
}
}