enact-core 0.0.1

Core agent runtime for Enact - Graph-Native AI agents
Documentation
//! Checkpoint types for save/resume execution

use crate::kernel::{GraphId, RunId};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use svix_ksuid::KsuidLike;

/// Checkpoint - saved state of execution
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Checkpoint {
    /// Unique checkpoint ID
    pub id: String,
    /// Run this checkpoint belongs to
    pub run_id: RunId,
    /// Graph being executed
    pub graph_id: Option<GraphId>,
    /// Current node in execution
    pub current_node: Option<String>,
    /// State at this checkpoint
    pub state: Value,
    /// Messages history (for LLM agents)
    pub messages: Vec<MessageRecord>,
    /// Tool results collected so far
    pub tool_results: HashMap<String, Value>,
    /// Created timestamp
    pub created_at: chrono::DateTime<chrono::Utc>,
    /// Metadata
    pub metadata: HashMap<String, Value>,
}

/// Message record for checkpoint
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageRecord {
    pub role: String,
    pub content: String,
}

impl Checkpoint {
    /// Create a new checkpoint
    pub fn new(run_id: RunId) -> Self {
        Self {
            id: format!("ckpt_{}", svix_ksuid::Ksuid::new(None, None)),
            run_id,
            graph_id: None,
            current_node: None,
            state: Value::Null,
            messages: Vec::new(),
            tool_results: HashMap::new(),
            created_at: chrono::Utc::now(),
            metadata: HashMap::new(),
        }
    }

    /// Set the current state
    pub fn with_state(mut self, state: Value) -> Self {
        self.state = state;
        self
    }

    /// Set the current node
    pub fn with_node(mut self, node: impl Into<String>) -> Self {
        self.current_node = Some(node.into());
        self
    }

    /// Add a message to history
    pub fn add_message(&mut self, role: impl Into<String>, content: impl Into<String>) {
        self.messages.push(MessageRecord {
            role: role.into(),
            content: content.into(),
        });
    }

    /// Add a tool result
    pub fn add_tool_result(&mut self, tool_name: impl Into<String>, result: Value) {
        self.tool_results.insert(tool_name.into(), result);
    }
}