aios_protocol/
identity.rs1use crate::ids::AgentId;
5use crate::memory::SoulProfile;
6
7pub trait AgentIdentityProvider: Send + Sync + std::fmt::Debug {
12 fn agent_id(&self) -> &AgentId;
14
15 fn soul_profile(&self) -> &SoulProfile;
17
18 fn did(&self) -> Option<&str> {
20 None
21 }
22
23 fn sign_jwt(&self, _audience: &str, _ttl_secs: u64) -> Option<String> {
25 None
26 }
27
28 fn capabilities(&self) -> &[String] {
30 &[]
31 }
32
33 fn economic_mode(&self) -> &str {
35 "sovereign"
36 }
37
38 fn policy_allows(&self, _action: &str) -> bool {
40 true
41 }
42
43 fn persona_block(&self) -> String {
45 let soul = self.soul_profile();
46 let mut block = format!("You are {} — {}.", soul.name, soul.mission);
47 if let Some(did) = self.did() {
48 block.push_str(&format!("\nIdentity: {did}"));
49 }
50 let caps = self.capabilities();
51 if !caps.is_empty() {
52 block.push_str(&format!("\nCapabilities: {}", caps.join(", ")));
53 }
54 block.push_str(&format!("\nEconomic mode: {}", self.economic_mode()));
55 block
56 }
57}
58
59#[derive(Debug, Clone, Default)]
61pub struct BasicIdentity {
62 pub agent_id: AgentId,
63 pub soul: SoulProfile,
64}
65
66impl BasicIdentity {
67 pub fn new(name: impl Into<String>, mission: impl Into<String>) -> Self {
68 Self {
69 agent_id: AgentId::default(),
70 soul: SoulProfile {
71 name: name.into(),
72 mission: mission.into(),
73 ..Default::default()
74 },
75 }
76 }
77
78 pub fn with_id(mut self, id: AgentId) -> Self {
79 self.agent_id = id;
80 self
81 }
82}
83
84impl AgentIdentityProvider for BasicIdentity {
85 fn agent_id(&self) -> &AgentId {
86 &self.agent_id
87 }
88
89 fn soul_profile(&self) -> &SoulProfile {
90 &self.soul
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn basic_identity_default() {
100 let id = BasicIdentity::default();
101 assert_eq!(id.soul_profile().name, "Agent OS agent");
102 assert_eq!(
103 id.soul_profile().mission,
104 "Run tool-mediated work safely and reproducibly"
105 );
106 }
107
108 #[test]
109 fn basic_identity_custom_name_mission() {
110 let id = BasicIdentity::new("Arcan Prime", "Runtime cognition for the Agent OS");
111 assert_eq!(id.soul_profile().name, "Arcan Prime");
112 assert_eq!(
113 id.soul_profile().mission,
114 "Runtime cognition for the Agent OS"
115 );
116 }
117
118 #[test]
119 fn basic_identity_with_id() {
120 let custom_id = AgentId::from_string("agt_custom_001");
121 let id = BasicIdentity::new("test", "test mission").with_id(custom_id.clone());
122 assert_eq!(id.agent_id(), &custom_id);
123 }
124
125 #[test]
126 fn trait_defaults_no_did() {
127 let id = BasicIdentity::default();
128 assert!(id.did().is_none());
129 }
130
131 #[test]
132 fn trait_defaults_no_jwt() {
133 let id = BasicIdentity::default();
134 assert!(id.sign_jwt("aud", 3600).is_none());
135 }
136
137 #[test]
138 fn trait_defaults_empty_capabilities() {
139 let id = BasicIdentity::default();
140 assert!(id.capabilities().is_empty());
141 }
142
143 #[test]
144 fn trait_defaults_sovereign_mode() {
145 let id = BasicIdentity::default();
146 assert_eq!(id.economic_mode(), "sovereign");
147 }
148
149 #[test]
150 fn trait_defaults_policy_allows_all() {
151 let id = BasicIdentity::default();
152 assert!(id.policy_allows("any_action"));
153 assert!(id.policy_allows("fs:write"));
154 }
155
156 #[test]
157 fn persona_block_basic() {
158 let id = BasicIdentity::new("Arcan", "Agent runtime");
159 let block = id.persona_block();
160 assert!(block.contains("You are Arcan"));
161 assert!(block.contains("Agent runtime"));
162 assert!(block.contains("Economic mode: sovereign"));
163 assert!(!block.contains("Identity:"));
165 assert!(!block.contains("Capabilities:"));
166 }
167
168 #[test]
169 fn persona_block_with_did_and_caps() {
170 #[derive(Debug)]
172 struct RichIdentity {
173 id: AgentId,
174 soul: SoulProfile,
175 did: String,
176 caps: Vec<String>,
177 }
178
179 impl AgentIdentityProvider for RichIdentity {
180 fn agent_id(&self) -> &AgentId {
181 &self.id
182 }
183 fn soul_profile(&self) -> &SoulProfile {
184 &self.soul
185 }
186 fn did(&self) -> Option<&str> {
187 Some(&self.did)
188 }
189 fn capabilities(&self) -> &[String] {
190 &self.caps
191 }
192 fn economic_mode(&self) -> &str {
193 "hustle"
194 }
195 }
196
197 let rich = RichIdentity {
198 id: AgentId::default(),
199 soul: SoulProfile {
200 name: "Agent X".into(),
201 mission: "Do things".into(),
202 ..Default::default()
203 },
204 did: "did:key:z6MkTest123".into(),
205 caps: vec!["chat:send".into(), "fs:read".into()],
206 };
207
208 let block = rich.persona_block();
209 assert!(block.contains("You are Agent X"));
210 assert!(block.contains("Identity: did:key:z6MkTest123"));
211 assert!(block.contains("Capabilities: chat:send, fs:read"));
212 assert!(block.contains("Economic mode: hustle"));
213 }
214}