use serde::{Deserialize, Serialize};
use crate::error::Result;
use crate::types::{KgExportResponse, KgPathResponse, KgQueryResponse};
use crate::DakeraClient;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KnowledgeGraphRequest {
pub agent_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub depth: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min_similarity: Option<f32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KnowledgeNode {
pub id: String,
pub content: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub importance: Option<f32>,
#[serde(default)]
pub metadata: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KnowledgeEdge {
pub source: String,
pub target: String,
pub similarity: f32,
#[serde(skip_serializing_if = "Option::is_none")]
pub relationship: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct KnowledgeGraphResponse {
pub nodes: Vec<KnowledgeNode>,
pub edges: Vec<KnowledgeEdge>,
#[serde(skip_serializing_if = "Option::is_none")]
pub clusters: Option<Vec<Vec<String>>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FullKnowledgeGraphRequest {
pub agent_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_nodes: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min_similarity: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cluster_threshold: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_edges_per_node: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SummarizeRequest {
pub agent_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_ids: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_type: Option<String>,
#[serde(default)]
pub dry_run: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SummarizeResponse {
pub summary: String,
pub source_count: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub new_memory_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeduplicateRequest {
pub agent_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub threshold: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub memory_type: Option<String>,
#[serde(default)]
pub dry_run: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeduplicateResponse {
pub duplicates_found: usize,
pub removed_count: usize,
pub groups: Vec<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrossAgentNetworkRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub agent_ids: Option<Vec<String>>,
pub min_similarity: f32,
pub max_nodes_per_agent: usize,
pub min_importance: f32,
pub max_cross_edges: usize,
}
impl Default for CrossAgentNetworkRequest {
fn default() -> Self {
Self {
agent_ids: None,
min_similarity: 0.3,
max_nodes_per_agent: 50,
min_importance: 0.0,
max_cross_edges: 200,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentNetworkInfo {
pub agent_id: String,
pub memory_count: usize,
pub avg_importance: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentNetworkNode {
pub id: String,
pub agent_id: String,
pub content: String,
pub importance: f32,
pub tags: Vec<String>,
pub memory_type: String,
pub created_at: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentNetworkEdge {
pub source: String,
pub target: String,
pub source_agent: String,
pub target_agent: String,
pub similarity: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentNetworkStats {
pub total_agents: usize,
pub total_nodes: usize,
pub total_cross_edges: usize,
pub density: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CrossAgentNetworkResponse {
pub agents: Vec<AgentNetworkInfo>,
pub nodes: Vec<AgentNetworkNode>,
pub edges: Vec<AgentNetworkEdge>,
pub stats: AgentNetworkStats,
#[serde(default)]
pub node_count: usize,
}
impl DakeraClient {
pub async fn knowledge_graph(
&self,
request: KnowledgeGraphRequest,
) -> Result<KnowledgeGraphResponse> {
let url = format!("{}/v1/knowledge/graph", self.base_url);
let response = self.client.post(&url).json(&request).send().await?;
self.handle_response(response).await
}
pub async fn full_knowledge_graph(
&self,
request: FullKnowledgeGraphRequest,
) -> Result<KnowledgeGraphResponse> {
let url = format!("{}/v1/knowledge/graph/full", self.base_url);
let response = self.client.post(&url).json(&request).send().await?;
self.handle_response(response).await
}
pub async fn summarize(&self, request: SummarizeRequest) -> Result<SummarizeResponse> {
let url = format!("{}/v1/knowledge/summarize", self.base_url);
let response = self.client.post(&url).json(&request).send().await?;
self.handle_response(response).await
}
pub async fn deduplicate(&self, request: DeduplicateRequest) -> Result<DeduplicateResponse> {
let url = format!("{}/v1/knowledge/deduplicate", self.base_url);
let response = self.client.post(&url).json(&request).send().await?;
self.handle_response(response).await
}
pub async fn cross_agent_network(
&self,
request: CrossAgentNetworkRequest,
) -> Result<CrossAgentNetworkResponse> {
let url = format!("{}/v1/knowledge/network/cross-agent", self.base_url);
let response = self.client.post(&url).json(&request).send().await?;
self.handle_response(response).await
}
pub async fn knowledge_query(
&self,
agent_id: &str,
root_id: Option<&str>,
edge_type: Option<&str>,
min_weight: Option<f32>,
max_depth: Option<u32>,
limit: Option<usize>,
) -> Result<KgQueryResponse> {
let mut url = format!("{}/v1/knowledge/query?agent_id={}", self.base_url, agent_id);
if let Some(v) = root_id {
url.push_str(&format!("&root_id={}", v));
}
if let Some(v) = edge_type {
url.push_str(&format!("&edge_type={}", v));
}
if let Some(v) = min_weight {
url.push_str(&format!("&min_weight={}", v));
}
if let Some(v) = max_depth {
url.push_str(&format!("&max_depth={}", v));
}
if let Some(v) = limit {
url.push_str(&format!("&limit={}", v));
}
let response = self.client.get(&url).send().await?;
self.handle_response(response).await
}
pub async fn knowledge_path(
&self,
agent_id: &str,
from_id: &str,
to_id: &str,
) -> Result<KgPathResponse> {
let url = format!(
"{}/v1/knowledge/path?agent_id={}&from={}&to={}",
self.base_url, agent_id, from_id, to_id
);
let response = self.client.get(&url).send().await?;
self.handle_response(response).await
}
pub async fn knowledge_export(
&self,
agent_id: &str,
format: Option<&str>,
) -> Result<KgExportResponse> {
let fmt = format.unwrap_or("json");
let url = format!(
"{}/v1/knowledge/export?agent_id={}&format={}",
self.base_url, agent_id, fmt
);
let response = self.client.get(&url).send().await?;
self.handle_response(response).await
}
}