aethellib 0.9.6

Composable text generation primitives over target-specific TOML corpora with provenance tracking.
Documentation
//! typed api example showing plan builder + compiled execution.

use aethellib::{engine::combinators, prelude::*};

fn main() {
    let corpus = Corpus::from_files(
        &["examples/data/weapon_test_data.toml"],
        "weapon",
        None,
        None,
    )
    .expect("failed to load weapon corpus");

    let weapon_name = RuleKey::new("weapon_name").expect("rule key should be valid");
    let full_name = RuleKey::new("full_name").expect("rule key should be valid");
    let display_name = RuleKey::new("display_name").expect("rule key should be valid");

    let primitives = PoolRef::new("name", "primitives").expect("pool ref should be valid");
    let prefix = PoolRef::new("name", "prefix").expect("pool ref should be valid");
    let kind = PoolRef::new("type", "type").expect("pool ref should be valid");
    let suffix = PoolRef::new("name", "suffix").expect("pool ref should be valid");

    let compiled = PlanBuilder::new(&corpus)
        .rule(&weapon_name, combinators::pick(primitives, Some(3), ""))
        .rule(
            &full_name,
            combinators::join([
                combinators::pick(prefix, None, ""),
                combinators::lit(" "),
                combinators::recall(&weapon_name),
                combinators::lit(" the "),
                combinators::pick(kind, None, ""),
                combinators::chance(
                    0.85,
                    combinators::join([combinators::lit(" "), combinators::pick(suffix, None, "")]),
                ),
            ]),
        )
        .rule(
            &display_name,
            combinators::custom([full_name.clone()], {
                move |ctx, _rng| {
                    let weapon = ctx.require(&full_name)?;
                    Ok(ComposedValue {
                        value: format!("{}!", weapon.value),
                        provenance: weapon.provenance.clone(),
                    })
                }
            }),
        )
        .validate()
        .expect("plan validation failed")
        .compile()
        .expect("plan compilation failed");

    let mut rng = rand::rng();
    let ctx = compiled.generate(&mut rng).expect("generation failed");

    println!(
        "Generated weapon: {}",
        ctx.require(&display_name)
            .expect("display_name should exist")
            .value,
    );
}