use super::EffectActor;
use crate::runtime::{Molecule, ReactorHandle};
use crate::value::Value;
use crate::Error;
use async_trait::async_trait;
use tokio::io::AsyncWriteExt;
pub struct TerminalWriteActor;
#[async_trait]
impl EffectActor for TerminalWriteActor {
fn kind_name(&self) -> &'static str {
"TerminalWrite"
}
async fn run(&self, request: Molecule, handle: ReactorHandle) -> Result<(), Error> {
let stream = request
.fields
.get("stream")
.ok_or_else(|| Error::Runtime("TerminalWrite missing stream".into()))?
.as_string()?
.to_string();
let content = request
.fields
.get("content")
.ok_or_else(|| Error::Runtime("TerminalWrite missing content".into()))?
.as_string()?
.to_string();
let newline = request
.fields
.get("newline")
.ok_or_else(|| Error::Runtime("TerminalWrite missing newline".into()))?
.as_bool()?;
let markdown = request
.fields
.get("markdown")
.map(|v| v.as_bool().unwrap_or(false))
.unwrap_or(false);
if markdown {
let body = content.clone();
tokio::task::spawn_blocking(move || {
let skin = termimad::MadSkin::default();
skin.print_text(&body);
})
.await
.map_err(|e| Error::Runtime(format!("termimad task join: {e}")))?;
} else {
let line = if newline {
format!("{content}\n")
} else {
content
};
match stream.as_str() {
"stderr" => {
let mut stderr = tokio::io::stderr();
stderr.write_all(line.as_bytes()).await.map_err(Error::Io)?;
}
_ => {
let mut stdout = tokio::io::stdout();
stdout.write_all(line.as_bytes()).await.map_err(Error::Io)?;
}
}
}
let mut updated = request.clone();
updated
.fields
.insert("status".into(), Value::String("Done".into()));
handle.emit(updated).await
}
}