thal 0.0.1

Reactive semantic runtime — molecules, reactions, and effect actors for building LLM-backed applications as dataflow programs.
Documentation
use std::time::Duration;
use thal::value::Value;
use thal::Reactor;

const PROGRAM: &str = r#"
reaction Greet {
    when:  Tick(t)
    where: t.sequence == 1
    emit:  TerminalWrite { content: "hello, thal" }
}

reaction Init {
    when: Boot(b)
    emit: Timer { interval: 50ms }
}
"#;

#[tokio::test(flavor = "multi_thread")]
async fn terminal_write_actor_runs() {
    let program = thal::load_str(PROGRAM).expect("load");
    let reactor = Reactor::new(program);
    let store = reactor.store();
    let task = tokio::spawn(reactor.run());

    tokio::time::sleep(Duration::from_millis(150)).await;
    task.abort();

    // Plan 08's delta-pinning evaluation fires Greet's binding-tuple exactly
    // once: only the Tick whose sequence == 1 satisfies the `where` filter,
    // and subsequent Ticks pin a different binding that fails the filter.
    let writes = store.scan_by_name("TerminalWrite");
    assert_eq!(
        writes.len(),
        1,
        "expected exactly one TerminalWrite under delta-pinning, got {}",
        writes.len()
    );

    let m = &writes[0];
    assert_eq!(
        m.fields["content"],
        Value::String("hello, thal".into()),
        "content preserved through the actor round-trip"
    );
    assert_eq!(
        m.fields["status"],
        Value::String("Done".into()),
        "actor should have driven Pending -> Done via the merge clause"
    );
}