1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! `AgentIdentities` resource — register and manage agent DIDs.
//!
//! Mirrors the Python SDK's `client.agent_identities.*` surface.
use serde_json::{json, Map, Value};
use crate::error::Result;
use crate::http::HttpClient;
/// Agent-identity lifecycle.
///
/// Access via [`crate::Areev::agent_identities`]. Requires: admin scope
/// for [`AgentIdentities::register`] and [`AgentIdentities::deactivate`].
pub struct AgentIdentities<'a> {
http: &'a HttpClient,
memory_id: String,
}
impl<'a> AgentIdentities<'a> {
/// Internal constructor — use [`crate::Areev::agent_identities`].
pub(crate) fn new(http: &'a HttpClient, memory_id: String) -> Self {
Self { http, memory_id }
}
/// Register a new agent identity. Requires: admin scope. Emits an
/// audit event.
///
/// `display_name` and `scopes` are **required by the live server**
/// (it deserializes into its `AgentIdentity` struct, whose fields are
/// `agent_id`, `display_name`, `delegated_by`, `scopes`, …). Each
/// entry in `scopes` is an `AgentScope` JSON object:
/// `{"namespaces": [...], "grain_types": [...], "permission": "Read"
/// | "ReadWrite" | "Admin"}` (empty `namespaces`/`grain_types` mean
/// "all"). When `scopes` is empty a single read-only all-access scope
/// is sent. `delegated_by` is optional (the delegating identity's id).
pub async fn register(
&self,
agent_id: &str,
display_name: &str,
scopes: &[Value],
delegated_by: Option<&str>,
) -> Result<Value> {
let mut body = Map::new();
body.insert("agent_id".into(), Value::String(agent_id.to_string()));
body.insert(
"display_name".into(),
Value::String(display_name.to_string()),
);
let scopes = if scopes.is_empty() {
vec![json!({ "namespaces": [], "grain_types": [], "permission": "Read" })]
} else {
scopes.to_vec()
};
body.insert("scopes".into(), Value::Array(scopes));
if let Some(d) = delegated_by {
body.insert("delegated_by".into(), Value::String(d.to_string()));
}
let path = format!("/memories/{}/agents/identities", self.memory_id);
self.http._post(&path, Some(&Value::Object(body))).await
}
/// List registered agent identities.
pub async fn list(&self) -> Result<Value> {
let path = format!("/memories/{}/agents/identities", self.memory_id);
self.http._get(&path, None).await
}
/// Get one agent identity by id.
pub async fn get(&self, agent_id: &str) -> Result<Value> {
let path = format!(
"/memories/{}/agents/identities/{}",
self.memory_id, agent_id
);
self.http._get(&path, None).await
}
/// Deactivate an agent identity. Requires: admin scope. Emits an
/// audit event.
pub async fn deactivate(&self, agent_id: &str, opts: Option<Value>) -> Result<Value> {
let body = opts.unwrap_or_else(|| Value::Object(Map::new()));
let path = format!(
"/memories/{}/agents/identities/{}/deactivate",
self.memory_id, agent_id
);
self.http._post(&path, Some(&body)).await
}
}