atman-runtime 1.9.1

atman flow execution runtime: evaluator, tool dispatch, provider dispatch, executor, memory stores
Documentation
use atman_runtime::stream::StreamFrame;
use atman_runtime::tool::{Tool, ToolArgs};
use atman_runtime::tools::{self, term::TermSpawn};
use atman_runtime::{Executor, Value};
use tokio::sync::broadcast;

#[tokio::test]
async fn term_spawn_emits_terminal_chunk_to_stream() {
    let (stream_tx, mut rx) = broadcast::channel::<StreamFrame>(256);
    let mut ex = Executor::new();
    tools::register_tier_zero(&ex.tools);
    let term_reg = tools::register_terminal(&ex.tools);
    let dir = std::env::temp_dir().join(format!("atman_term_e2e_{}", uuid::Uuid::now_v7()));
    ex.tool_ctx = ex
        .tool_ctx
        .clone()
        .with_term_registry(term_reg)
        .with_session_dir(dir);
    ex.tool_ctx.stream_tx = Some(stream_tx);

    let args = ToolArgs {
        positional: vec![],
        named: vec![
            ("cmd".into(), Value::Str("echo hello_term_test".into())),
            ("rows".into(), Value::Int(5)),
            ("cols".into(), Value::Int(40)),
        ],
    };
    let v = TermSpawn.call(args, &ex.tool_ctx).await.unwrap();
    let Value::Struct(_) = v else {
        panic!("expected struct")
    };

    let mut got_chunk = false;
    let mut got_exited = false;
    let deadline = tokio::time::Instant::now() + std::time::Duration::from_secs(3);
    loop {
        match tokio::time::timeout_at(deadline, rx.recv()).await {
            Ok(Ok(StreamFrame::TerminalChunk { bytes, .. })) => {
                if String::from_utf8_lossy(&bytes).contains("hello_term_test") {
                    got_chunk = true;
                }
            }
            Ok(Ok(StreamFrame::TerminalExited { .. })) => {
                got_exited = true;
                if got_chunk {
                    break;
                }
            }
            Ok(Ok(_)) => {}
            Ok(Err(_)) => break,
            Err(_) => break,
        }
    }
    assert!(got_chunk, "TerminalChunk with echo output not received");
    assert!(got_exited, "TerminalExited not received");
}