use async_trait::async_trait;
use chrono::Utc;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum EvidenceType {
ToolOutput,
ExternalApi,
HumanInput,
DocumentReference,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum UaicpState {
Intake,
Planning,
Executing,
Verification,
Delivery,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum RollbackActionType {
CompensatingToolCall,
RevertApi,
ManualIntervention,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PolicyOutcomeStatus {
Allow,
Deny,
NeedsReview,
FailSafe,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvidenceObject {
pub evidence_id: String,
pub evidence_type: EvidenceType,
pub source: String,
pub collected_at: String, #[serde(skip_serializing_if = "Option::is_none")]
pub hash: Option<String>, #[serde(skip_serializing_if = "Option::is_none")]
pub parent_trace_id: Option<String>, pub payload: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UaicpRollbackAction {
pub action_type: RollbackActionType,
pub payload: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UaicpStreaming {
pub chunk_id: String,
pub is_final: bool,
pub content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentIdentity {
pub agent_id: String,
pub agent_type: String,
pub framework: String,
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyOutcome {
pub status: PolicyOutcomeStatus,
pub reason_code: String,
pub resolution: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageEnvelope {
pub uaicp_version: String,
pub trace_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_trace_id: Option<String>, pub state: UaicpState,
pub identity: AgentIdentity,
pub evidence: Vec<EvidenceObject>,
#[serde(skip_serializing_if = "Option::is_none")]
pub outcome: Option<PolicyOutcome>,
#[serde(skip_serializing_if = "Option::is_none")]
pub streaming: Option<UaicpStreaming>, #[serde(skip_serializing_if = "Option::is_none")]
pub rollback_action: Option<UaicpRollbackAction>, }
#[derive(Debug, Clone)]
pub struct PolicyResult {
pub allowed: bool,
pub reason: String,
pub requires_review: bool,
}
#[async_trait]
pub trait UaicpAdapter: Send + Sync {
type FrameworkState;
type FrameworkToolCall;
fn map_to_envelope(&self, state: &Self::FrameworkState) -> MessageEnvelope;
fn normalize_evidence(&self, tool_call: &Self::FrameworkToolCall) -> EvidenceObject;
async fn verify_gates(&self, envelope: &MessageEnvelope) -> bool;
async fn enforce_policy(&self, envelope: &MessageEnvelope) -> PolicyResult;
fn stream_partial(&self, chunk: &serde_json::Value) -> Option<UaicpStreaming> {
let _ = chunk;
None
}
fn rollback_payload(&self, envelope: &MessageEnvelope) -> Option<UaicpRollbackAction> {
let _ = envelope;
None
}
}
pub fn now_iso() -> String {
Utc::now().to_rfc3339()
}