mecha10-core 4.2.9

Mecha10 core runtime and foundational types
Documentation
//! Access to the per-tree, non-persistent, in-memory scratch store.

use super::Context;
use crate::blackboard::Blackboard;

impl Context {
    /// Get this context's [`Blackboard`] - a synchronous, in-memory key/value scratch store
    /// shared by sibling nodes within a single running behavior tree.
    ///
    /// Unlike `ctx.state_manager()`, this is **not** persisted anywhere; it exists only for the
    /// lifetime of this `Context` (and is lost on process restart). Use it for cheap scratch
    /// data that sibling nodes need to share during a single run of a tree, without a pub/sub
    /// topic round-trip through `message_bus`.
    ///
    /// # Example
    ///
    /// ```rust,no_run
    /// # use mecha10_core::prelude::*;
    /// # async fn example(ctx: &Context) {
    /// ctx.blackboard().set("last_target", serde_json::json!({"x": 1.0, "y": 2.0}));
    ///
    /// if let Some(target) = ctx.blackboard().get("last_target") {
    ///     println!("target: {target}");
    /// }
    /// # }
    /// ```
    pub fn blackboard(&self) -> &Blackboard {
        &self.blackboard
    }
}

// Without the "messaging" feature, `Context::new` skips the infrastructure-config/Redis
// connection path entirely (see the `#[cfg(feature = "messaging")]` gating in
// `context::lifecycle::Context::new`), so it builds without any real infra present. With
// "messaging" enabled it requires a real `config/infrastructure.<env>.yaml` (or
// `MECHA10_REDIS_URL`/`mecha10.json`) and a reachable Redis - neither of which exist in this
// repo/CI - so these tests follow the same precedent as `node::tests` (see `src/node.rs`) and
// only run in the messaging-less build.
#[cfg(all(test, not(feature = "messaging")))]
mod tests {
    use super::*;

    #[tokio::test]
    async fn fresh_context_blackboard_starts_empty() {
        let ctx = Context::new("blackboard-test-node")
            .await
            .expect("context should build without messaging");

        assert!(ctx.blackboard().is_empty());
        assert_eq!(ctx.blackboard().len(), 0);
    }

    #[tokio::test]
    async fn context_clone_shares_the_same_blackboard() {
        let ctx = Context::new("blackboard-test-node-clone")
            .await
            .expect("context should build without messaging");
        let cloned = ctx.clone();

        ctx.blackboard().set("key", serde_json::json!("value"));

        assert_eq!(cloned.blackboard().get("key"), Some(serde_json::json!("value")));
    }
}