agentlog 0.1.2

CLI flight recorder for AI coding agents - capture, store, and replay AI sessions
Documentation
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum EventType {
    SessionStart,
    SessionEnd,
    ProcessExec,
    FileChange,
    GitCommit,
    Error,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Actor {
    pub r#type: ActorType,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub agent_name: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ActorType {
    Ai,
    Human,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Event {
    pub event_id: String,
    pub timestamp: DateTime<Utc>,
    pub session_id: String,
    pub r#type: EventType,
    pub actor: Actor,
    pub payload: Payload,
}

impl Event {
    pub fn new(session_id: String, event_type: EventType, actor: Actor, payload: Payload) -> Self {
        Self {
            event_id: Uuid::new_v4().to_string(),
            timestamp: Utc::now(),
            session_id,
            r#type: event_type,
            actor,
            payload,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Payload {
    SessionStart {
        cwd: String,
        command: String,
    },
    SessionEnd {
        exit_code: i32,
        duration_ms: u64,
    },
    ProcessExec {
        command: String,
        args: Vec<String>,
    },
    FileChange {
        file: String,
        lines_added: usize,
        lines_removed: usize,
        #[serde(skip_serializing_if = "Option::is_none")]
        diff: Option<String>,
    },
    GitCommit {
        hash: String,
        message: String,
    },
    Error {
        message: String,
    },
}