areev 0.2.0

Rust SDK for the Areev knowledge database — gRPC and HTTP transports
Documentation
//! `Goals` resource — Goal grains, goal trees, delegation, and state.
//!
//! Mirrors the Python SDK's `client.goals.*` surface.

use serde_json::{json, Map, Value};

use crate::error::Result;
use crate::http::HttpClient;

/// Goal-grain lifecycle.
///
/// Access via [`crate::Areev::goals`].
pub struct Goals<'a> {
    http: &'a HttpClient,
    memory_id: String,
}

impl<'a> Goals<'a> {
    /// Internal constructor — use [`crate::Areev::goals`].
    pub(crate) fn new(http: &'a HttpClient, memory_id: String) -> Self {
        Self { http, memory_id }
    }

    /// Create a goal under `session_id` (optionally nested via
    /// `parent_goal_hash`).
    pub async fn create(
        &self,
        session_id: &str,
        description: &str,
        criteria: Option<&str>,
        parent_goal_hash: Option<&str>,
        priority: Option<&str>,
    ) -> Result<Value> {
        let mut body = Map::new();
        body.insert("description".into(), Value::String(description.to_string()));
        if let Some(c) = criteria {
            body.insert("criteria".into(), Value::String(c.to_string()));
        }
        if let Some(p) = parent_goal_hash {
            body.insert("parent_goal_hash".into(), Value::String(p.to_string()));
        }
        if let Some(p) = priority {
            body.insert("priority".into(), Value::String(p.to_string()));
        }
        let path = format!(
            "/memories/{}/sessions/{}/goals/create",
            self.memory_id, session_id
        );
        self.http._post(&path, Some(&Value::Object(body))).await
    }

    /// Return the goal tree for a session.
    pub async fn tree(&self, session_id: &str) -> Result<Value> {
        let path = format!(
            "/memories/{}/sessions/{}/goals/tree",
            self.memory_id, session_id
        );
        self.http._get(&path, None).await
    }

    /// List goals currently blocked by unmet dependencies.
    pub async fn blocked(&self, session_id: &str) -> Result<Value> {
        let path = format!(
            "/memories/{}/sessions/{}/goals/blocked",
            self.memory_id, session_id
        );
        self.http._get(&path, None).await
    }

    /// Delegate a goal to another agent. Emits an audit event.
    pub async fn delegate(
        &self,
        goal_hash: &str,
        delegate_to: &str,
        description: &str,
    ) -> Result<Value> {
        let body = json!({ "delegate_to": delegate_to, "description": description });
        let path = format!("/memories/{}/goals/{}/delegate", self.memory_id, goal_hash);
        self.http._post(&path, Some(&body)).await
    }

    /// Transition a goal's state (e.g. `active` → `completed`).
    pub async fn update_state(
        &self,
        goal_hash: &str,
        state: &str,
        reason: Option<&str>,
    ) -> Result<Value> {
        let mut body = Map::new();
        body.insert("state".into(), Value::String(state.to_string()));
        if let Some(r) = reason {
            body.insert("reason".into(), Value::String(r.to_string()));
        }
        let path = format!("/memories/{}/goals/{}/state", self.memory_id, goal_hash);
        self.http._put(&path, Some(&Value::Object(body))).await
    }
}