systemprompt-agent 0.2.2

Agent-to-Agent (A2A) protocol for systemprompt.io AI governance: streaming, JSON-RPC models, task lifecycle, .well-known discovery, and governed agent orchestration.
Documentation
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use systemprompt_identifiers::{ContextId, McpExecutionId, MessageId, SkillId, TaskId};

pub use systemprompt_models::{
    CreateContextRequest, UpdateContextRequest, UserContext, UserContextWithStats,
};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContextMessage {
    pub message_id: MessageId,
    pub role: String,
    pub created_at: DateTime<Utc>,
    pub sequence_number: i32,
    pub parts: Vec<serde_json::Value>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ContextDetail {
    pub context: UserContext,
    pub messages: Vec<ContextMessage>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ContextStateEvent {
    ToolExecutionCompleted {
        context_id: ContextId,
        execution_id: McpExecutionId,
        tool_name: String,
        server_name: String,
        output: Option<String>,
        #[serde(skip_serializing_if = "Option::is_none")]
        artifact: Option<super::a2a::Artifact>,
        status: String,
        timestamp: DateTime<Utc>,
    },
    TaskStatusChanged {
        task: super::a2a::Task,
        context_id: ContextId,
        timestamp: DateTime<Utc>,
    },
    ArtifactCreated {
        artifact: super::a2a::Artifact,
        task_id: TaskId,
        context_id: ContextId,
        timestamp: DateTime<Utc>,
    },
    SkillLoaded {
        skill_id: SkillId,
        skill_name: String,
        description: String,
        request_context: systemprompt_models::execution::context::RequestContext,
        tool_name: Option<String>,
        timestamp: DateTime<Utc>,
    },
    ContextCreated {
        context_id: ContextId,
        context: UserContext,
        timestamp: DateTime<Utc>,
    },
    ContextUpdated {
        context_id: ContextId,
        name: String,
        timestamp: DateTime<Utc>,
    },
    ContextDeleted {
        context_id: ContextId,
        timestamp: DateTime<Utc>,
    },
    Heartbeat {
        timestamp: DateTime<Utc>,
    },
    CurrentAgent {
        context_id: ContextId,
        agent_name: Option<String>,
        timestamp: DateTime<Utc>,
    },
}

impl ContextStateEvent {
    pub fn context_id(&self) -> Option<&str> {
        match self {
            Self::SkillLoaded {
                request_context, ..
            } => Some(request_context.context_id().as_str()),
            Self::Heartbeat { .. } => None,
            Self::ToolExecutionCompleted { context_id, .. }
            | Self::TaskStatusChanged { context_id, .. }
            | Self::ArtifactCreated { context_id, .. }
            | Self::ContextCreated { context_id, .. }
            | Self::ContextUpdated { context_id, .. }
            | Self::ContextDeleted { context_id, .. }
            | Self::CurrentAgent { context_id, .. } => Some(context_id.as_str()),
        }
    }

    pub const fn timestamp(&self) -> DateTime<Utc> {
        match self {
            Self::ToolExecutionCompleted { timestamp, .. }
            | Self::TaskStatusChanged { timestamp, .. }
            | Self::ArtifactCreated { timestamp, .. }
            | Self::SkillLoaded { timestamp, .. }
            | Self::ContextCreated { timestamp, .. }
            | Self::ContextUpdated { timestamp, .. }
            | Self::ContextDeleted { timestamp, .. }
            | Self::Heartbeat { timestamp }
            | Self::CurrentAgent { timestamp, .. } => *timestamp,
        }
    }
}