use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentCard {
pub name: String,
pub description: String,
pub protocol: String,
pub capabilities: Vec<AgentCapability>,
pub endpoint: String,
pub auth: AgentAuth,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentCapability {
pub id: String,
pub description: String,
pub input_schema: serde_json::Value,
pub output_schema: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentAuth {
pub auth_type: String,
pub header: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct A2ATaskRequest {
pub task_id: String,
pub capability: String,
pub input: serde_json::Value,
pub from_agent: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct A2ATaskResponse {
pub task_id: String,
pub status: String,
pub output: serde_json::Value,
pub error: Option<String>,
}
impl AgentCard {
pub fn pensyve_default(endpoint: &str) -> Self {
Self {
name: "pensyve-memory".to_string(),
description: "Universal memory runtime for AI agents — recall, remember, and forget across sessions".to_string(),
protocol: "a2a/v1".to_string(),
capabilities: vec![
AgentCapability {
id: "memory.recall".to_string(),
description: "Query memories by semantic similarity".to_string(),
input_schema: serde_json::json!({
"type": "object",
"properties": {
"query": {"type": "string"},
"limit": {"type": "integer", "default": 5},
"entity": {"type": "string"}
},
"required": ["query"]
}),
output_schema: serde_json::json!({
"type": "object",
"properties": {
"memories": {"type": "array"}
}
}),
},
AgentCapability {
id: "memory.remember".to_string(),
description: "Store a new memory".to_string(),
input_schema: serde_json::json!({
"type": "object",
"properties": {
"entity": {"type": "string"},
"fact": {"type": "string"},
"confidence": {"type": "number", "default": 0.8}
},
"required": ["entity", "fact"]
}),
output_schema: serde_json::json!({
"type": "object",
"properties": {
"memory_id": {"type": "string"}
}
}),
},
AgentCapability {
id: "memory.forget".to_string(),
description: "Delete memories for an entity".to_string(),
input_schema: serde_json::json!({
"type": "object",
"properties": {
"entity": {"type": "string"}
},
"required": ["entity"]
}),
output_schema: serde_json::json!({
"type": "object",
"properties": {
"forgotten_count": {"type": "integer"}
}
}),
},
],
endpoint: endpoint.to_string(),
auth: AgentAuth {
auth_type: "api_key".to_string(),
header: Some("X-Pensyve-Key".to_string()),
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_agent_card_default() {
let card = AgentCard::pensyve_default("http://localhost:8000");
assert_eq!(card.name, "pensyve-memory");
assert_eq!(card.protocol, "a2a/v1");
assert_eq!(card.capabilities.len(), 3);
assert_eq!(card.endpoint, "http://localhost:8000");
}
#[test]
fn test_agent_card_serialization() {
let card = AgentCard::pensyve_default("http://localhost:8000");
let json = serde_json::to_string(&card).unwrap();
assert!(json.contains("pensyve-memory"));
assert!(json.contains("memory.recall"));
assert!(json.contains("memory.remember"));
assert!(json.contains("memory.forget"));
}
#[test]
fn test_task_request_deserialization() {
let json = r#"{
"task_id": "task-123",
"capability": "memory.recall",
"input": {"query": "user preferences", "limit": 5},
"from_agent": "coding-assistant"
}"#;
let req: A2ATaskRequest = serde_json::from_str(json).unwrap();
assert_eq!(req.task_id, "task-123");
assert_eq!(req.capability, "memory.recall");
assert_eq!(req.from_agent, "coding-assistant");
}
#[test]
fn test_task_response_serialization() {
let resp = A2ATaskResponse {
task_id: "task-123".to_string(),
status: "completed".to_string(),
output: serde_json::json!({"memories": []}),
error: None,
};
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("completed"));
}
}