use std::sync::Arc;
use agentplane::prelude::*;
use serde_json::{Value, json};
#[derive(Debug)]
struct Greet;
#[async_trait::async_trait]
impl Skill for Greet {
fn descriptor(&self) -> SkillDescriptor {
SkillDescriptor::new("greet").provides("demo.greet")
}
async fn invoke(
&self,
cx: &mut StepCtx<'_>,
input: Tainted<Value>,
) -> Result<Outcome, SkillError> {
let at = cx.now().await?;
Ok(Outcome::done(
input.map(|v| json!({ "greeted": v, "at": at.to_string() })),
))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let store: Arc<dyn JournalStore> = Arc::new(RedbStore::open_in_memory()?);
let runtime = Runtime::builder(Arc::clone(&store))
.owner("hello-service")
.skill(Greet)
.build();
let outcome = runtime
.run("demo.greet", Tainted::trusted(json!({ "name": "world" })))
.await?;
println!("live: {:?} → {:?}", outcome.status, outcome.output);
let replayed = runtime.replay(outcome.run_id, Mode::Strict).await?;
println!("replay: {:?} → {:?}", replayed.status, replayed.output);
assert_eq!(outcome.output, replayed.output, "replay reproduced the run");
println!("\nSame answer, and the second time nothing happened.");
Ok(())
}