1use crate::agent_key_manager::{AgentKeyManager, AgentKeyManagerBuilder};
2use crate::config::AgentConfig;
3#[cfg(all(not(target_arch = "wasm32"), test))]
4use crate::did::SyncDIDResolver; use crate::error::{Error, Result};
6use crate::key_manager::KeyManager; #[cfg(not(target_arch = "wasm32"))]
8use crate::message::SecurityMode;
9#[cfg(not(target_arch = "wasm32"))]
10use crate::message_packing::{PackOptions, Packable, UnpackOptions, Unpackable};
11use async_trait::async_trait;
12#[cfg(feature = "native")]
13use reqwest::Client;
14#[cfg(target_arch = "wasm32")]
15use serde::de::DeserializeOwned;
16use serde_json::Value;
17use std::path::PathBuf;
18use std::sync::Arc;
19#[cfg(feature = "native")]
20use std::time::Duration;
21use tap_msg::didcomm::{PlainMessage, PlainMessageExt};
22use tap_msg::TapMessageBody;
23
24pub type EnhancedAgentInfo = (
26 String,
27 Vec<String>,
28 std::collections::HashMap<String, String>,
29);
30
31#[derive(Debug, Clone)]
33pub struct DeliveryResult {
34 pub did: String,
36 pub endpoint: String,
38 pub status: Option<u16>,
40 pub error: Option<String>,
42}
43
44#[cfg(not(target_arch = "wasm32"))]
75#[async_trait]
76#[cfg(not(target_arch = "wasm32"))]
77pub trait Agent {
78 fn get_agent_did(&self) -> &str;
80
81 async fn get_service_endpoint(&self, to: &str) -> Result<Option<String>>;
87
88 async fn send_message<
99 T: TapMessageBody + serde::Serialize + Send + Sync + std::fmt::Debug + 'static,
100 >(
101 &self,
102 message: &T,
103 to: Vec<&str>,
104 deliver: bool,
105 ) -> Result<(String, Vec<DeliveryResult>)>;
106
107 async fn receive_encrypted_message(&self, jwe_value: &Value) -> Result<()>;
118
119 async fn receive_plain_message(&self, message: PlainMessage) -> Result<()>;
128
129 async fn receive_message(&self, raw_message: &str) -> Result<PlainMessage>;
143
144 async fn send_typed<T: TapMessageBody + Send + Sync + std::fmt::Debug + 'static>(
154 &self,
155 message: PlainMessage<T>,
156 deliver: bool,
157 ) -> Result<(String, Vec<DeliveryResult>)> {
158 let plain_message = message.to_plain_message()?;
160 let to_vec: Vec<&str> = plain_message.to.iter().map(|s| s.as_str()).collect();
161
162 let body = serde_json::from_value::<T>(plain_message.body)?;
164 self.send_message(&body, to_vec, deliver).await
165 }
166
167 async fn send_with_context<T>(
180 &self,
181 message: &T,
182 deliver: bool,
183 ) -> Result<(String, Vec<DeliveryResult>)>
184 where
185 T: TapMessageBody
186 + tap_msg::message::MessageContext
187 + Send
188 + Sync
189 + std::fmt::Debug
190 + 'static,
191 {
192 let participant_dids = message.participant_dids();
194 let recipients: Vec<&str> = participant_dids
195 .iter()
196 .map(|s| s.as_str())
197 .filter(|&did| did != self.get_agent_did()) .collect();
199
200 let _routing_hints = message.routing_hints();
202
203 self.send_message(message, recipients, deliver).await
206 }
207
208 async fn send_typed_with_context<T>(
218 &self,
219 message: PlainMessage<T>,
220 deliver: bool,
221 ) -> Result<(String, Vec<DeliveryResult>)>
222 where
223 T: TapMessageBody
224 + tap_msg::message::MessageContext
225 + Send
226 + Sync
227 + std::fmt::Debug
228 + 'static,
229 {
230 let participants = message.extract_participants_with_context();
232 let _recipients: Vec<&str> = participants
233 .iter()
234 .map(|s| s.as_str())
235 .filter(|&did| did != self.get_agent_did()) .collect();
237
238 let _routing_hints = message.routing_hints();
240
241 let body = message.body;
243 self.send_with_context(&body, deliver).await
244 }
245
246 async fn receive_typed<T: TapMessageBody>(&self, raw_message: &str) -> Result<PlainMessage<T>> {
257 let plain_message = self.receive_message(raw_message).await?;
258 plain_message
259 .parse_as()
260 .map_err(|e| Error::Serialization(e.to_string()))
261 }
262}
263
264#[cfg(target_arch = "wasm32")]
266pub trait WasmAgent {
267 fn get_agent_did(&self) -> &str;
269
270 fn pack_message<T: TapMessageBody + serde::Serialize>(&self, message: &T) -> Result<String>;
272
273 fn unpack_message<T: TapMessageBody + DeserializeOwned>(
275 &self,
276 packed_message: &str,
277 ) -> Result<T>;
278}
279
280#[derive(Debug, Clone)]
282pub struct TapAgent {
283 pub config: AgentConfig,
285 key_manager: Arc<AgentKeyManager>,
287 #[cfg(all(not(target_arch = "wasm32"), test))]
289 resolver: Option<Arc<dyn SyncDIDResolver>>,
290 #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
292 http_client: Option<Client>,
293}
294
295impl TapAgent {
296 pub fn key_manager(&self) -> &Arc<AgentKeyManager> {
298 &self.key_manager
299 }
300
301 pub fn new(config: AgentConfig, key_manager: Arc<AgentKeyManager>) -> Self {
303 #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
304 {
305 let timeout = Duration::from_secs(config.timeout_seconds.unwrap_or(30));
306 let client = Client::builder().timeout(timeout).build().ok();
307
308 #[cfg(test)]
309 let agent = TapAgent {
310 config,
311 key_manager,
312 resolver: None,
313 http_client: client,
314 };
315
316 #[cfg(not(test))]
317 let agent = TapAgent {
318 config,
319 key_manager,
320 http_client: client,
321 };
322
323 agent
324 }
325
326 #[cfg(not(all(feature = "native", not(target_arch = "wasm32"))))]
327 {
328 #[cfg(all(not(target_arch = "wasm32"), test))]
329 let agent = TapAgent {
330 config,
331 key_manager,
332 resolver: None,
333 };
334
335 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
336 let agent = TapAgent {
337 config,
338 key_manager,
339 };
340
341 #[cfg(target_arch = "wasm32")]
342 let agent = TapAgent {
343 config,
344 key_manager,
345 };
346
347 agent
348 }
349 }
350
351 #[cfg(all(not(target_arch = "wasm32"), test))]
353 pub fn new_with_resolver(
354 config: AgentConfig,
355 key_manager: Arc<AgentKeyManager>,
356 resolver: Arc<dyn SyncDIDResolver>,
357 ) -> Self {
358 #[cfg(feature = "native")]
359 {
360 let timeout = Duration::from_secs(config.timeout_seconds.unwrap_or(30));
361 let client = Client::builder().timeout(timeout).build().ok();
362
363 TapAgent {
364 config,
365 key_manager,
366 resolver: Some(resolver),
367 http_client: client,
368 }
369 }
370
371 #[cfg(not(feature = "native"))]
372 {
373 TapAgent {
374 config,
375 key_manager,
376 resolver: Some(resolver),
377 }
378 }
379 }
380
381 pub async fn from_ephemeral_key() -> crate::error::Result<(Self, String)> {
390 use crate::did::{DIDGenerationOptions, KeyType};
391
392 let key_manager = AgentKeyManager::new();
394
395 let key = key_manager.generate_key(DIDGenerationOptions {
397 key_type: KeyType::Ed25519,
398 })?;
399
400 let config = AgentConfig::new(key.did.clone()).with_debug(true);
402
403 #[cfg(all(not(target_arch = "wasm32"), test))]
405 {
406 let resolver = Arc::new(crate::did::MultiResolver::default());
408 let agent = Self::new_with_resolver(config, Arc::new(key_manager), resolver);
409 Ok((agent, key.did))
410 }
411
412 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
413 {
414 let agent = Self::new(config, Arc::new(key_manager));
415 Ok((agent, key.did))
416 }
417
418 #[cfg(target_arch = "wasm32")]
419 {
420 let agent = Self::new(config, Arc::new(key_manager));
421 Ok((agent, key.did))
422 }
423 }
424
425 pub async fn from_stored_keys(did: Option<String>, debug: bool) -> Result<Self> {
438 use crate::storage::KeyStorage;
439
440 let key_manager_builder = AgentKeyManagerBuilder::new().load_from_default_storage();
442 let key_manager = key_manager_builder.build()?;
443
444 let dids = key_manager.list_keys()?;
446 if dids.is_empty() {
447 return Err(Error::Storage(
448 "No keys found in storage. Generate keys first with 'tap-agent-cli generate --save'".to_string(),
449 ));
450 }
451
452 let agent_did = if let Some(specified_did) = did {
454 if !dids.contains(&specified_did) {
455 return Err(Error::Storage(format!(
456 "Key with DID '{}' not found in storage",
457 specified_did
458 )));
459 }
460 specified_did
461 } else {
462 let storage = KeyStorage::load_default()?;
464 storage.default_did.unwrap_or_else(|| dids[0].clone())
465 };
466
467 let config = AgentConfig::new(agent_did).with_debug(debug);
469
470 #[cfg(all(not(target_arch = "wasm32"), test))]
472 {
473 let resolver = Arc::new(crate::did::MultiResolver::default());
475 Ok(TapAgent::new_with_resolver(
476 config,
477 Arc::new(key_manager),
478 resolver,
479 ))
480 }
481
482 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
483 {
484 Ok(TapAgent::new(config, Arc::new(key_manager)))
485 }
486
487 #[cfg(target_arch = "wasm32")]
488 {
489 Ok(TapAgent::new(config, Arc::new(key_manager)))
490 }
491 }
492
493 pub async fn from_private_key(
509 private_key: &[u8],
510 key_type: crate::did::KeyType,
511 debug: bool,
512 ) -> Result<(Self, String)> {
513 use crate::did::{DIDKeyGenerator, GeneratedKey};
514 use crate::did::{VerificationMaterial, VerificationMethod, VerificationMethodType};
515 use curve25519_dalek::edwards::CompressedEdwardsY;
516 use multibase::{encode, Base};
517
518 let key_manager = AgentKeyManager::new();
520
521 let generated_key = match key_type {
523 crate::did::KeyType::Ed25519 => {
524 if private_key.len() != 32 {
525 return Err(Error::Validation(format!(
526 "Invalid Ed25519 private key length: {}, expected 32 bytes",
527 private_key.len()
528 )));
529 }
530
531 let mut private_key_bytes = [0u8; 32];
533 private_key_bytes.copy_from_slice(&private_key[0..32]);
534
535 let signing_key = ed25519_dalek::SigningKey::from_bytes(&private_key_bytes);
536
537 let verifying_key = ed25519_dalek::VerifyingKey::from(&signing_key);
539 let public_key = verifying_key.to_bytes().to_vec();
540
541 let mut prefixed_key = vec![0xed, 0x01];
544 prefixed_key.extend_from_slice(&public_key);
545
546 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
548 let did = format!("did:key:{}", multibase_encoded);
549
550 let vm_id = format!("{}#{}", did, multibase_encoded);
552
553 let verification_method = VerificationMethod {
555 id: vm_id.clone(),
556 type_: VerificationMethodType::Ed25519VerificationKey2018,
557 controller: did.clone(),
558 verification_material: VerificationMaterial::Multibase {
559 public_key_multibase: multibase_encoded.clone(),
560 },
561 };
562
563 let x25519_method_and_agreement = {
565 if public_key.len() != 32 {
567 None
568 } else {
569 let edwards_y = match CompressedEdwardsY::from_slice(&public_key) {
571 Ok(point) => point,
572 Err(_) => {
573 return Err(Error::Cryptography(
574 "Failed to create Edwards point".to_string(),
575 ))
576 }
577 };
578
579 let edwards_point = match edwards_y.decompress() {
581 Some(point) => point,
582 None => {
583 return Err(Error::Cryptography(
584 "Failed to decompress Edwards point".to_string(),
585 ))
586 }
587 };
588
589 let montgomery_point = edwards_point.to_montgomery();
591
592 let x25519_key = montgomery_point.to_bytes();
594
595 let mut x25519_prefixed = vec![0xEC, 0x01];
597 x25519_prefixed.extend_from_slice(&x25519_key);
598
599 let x25519_multibase = encode(Base::Base58Btc, &x25519_prefixed);
601
602 let x25519_vm_id = format!("{}#{}", did, x25519_multibase);
604
605 let x25519_verification_method = VerificationMethod {
607 id: x25519_vm_id.clone(),
608 type_: VerificationMethodType::X25519KeyAgreementKey2019,
609 controller: did.clone(),
610 verification_material: VerificationMaterial::Multibase {
611 public_key_multibase: x25519_multibase,
612 },
613 };
614
615 Some((x25519_verification_method, x25519_vm_id))
616 }
617 };
618
619 let mut verification_methods = vec![verification_method.clone()];
621 let mut key_agreement = Vec::new();
622
623 if let Some((x25519_vm, x25519_id)) = x25519_method_and_agreement {
624 verification_methods.push(x25519_vm);
625 key_agreement.push(x25519_id);
626 }
627
628 let did_doc = crate::did::DIDDoc {
630 id: did.clone(),
631 verification_method: verification_methods,
632 authentication: vec![vm_id],
633 key_agreement,
634 assertion_method: Vec::new(),
635 capability_invocation: Vec::new(),
636 capability_delegation: Vec::new(),
637 service: Vec::new(),
638 };
639
640 GeneratedKey {
642 key_type: crate::did::KeyType::Ed25519,
643 did: did.clone(),
644 public_key,
645 private_key: private_key.to_vec(),
646 did_doc,
647 }
648 }
649 crate::did::KeyType::P256 => {
650 if private_key.len() != 32 {
651 return Err(Error::Validation(format!(
652 "Invalid P-256 private key length: {}, expected 32 bytes",
653 private_key.len()
654 )));
655 }
656
657 let signing_key = match p256::ecdsa::SigningKey::from_slice(private_key) {
659 Ok(key) => key,
660 Err(e) => {
661 return Err(Error::Cryptography(format!(
662 "Failed to create P-256 signing key: {:?}",
663 e
664 )))
665 }
666 };
667
668 let public_key = signing_key
670 .verifying_key()
671 .to_encoded_point(false)
672 .to_bytes()
673 .to_vec();
674
675 let mut prefixed_key = vec![0x12, 0x00];
678 prefixed_key.extend_from_slice(&public_key);
679
680 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
682 let did = format!("did:key:{}", multibase_encoded);
683
684 let vm_id = format!("{}#{}", did, multibase_encoded);
686
687 let verification_method = VerificationMethod {
689 id: vm_id.clone(),
690 type_: VerificationMethodType::EcdsaSecp256k1VerificationKey2019, controller: did.clone(),
692 verification_material: VerificationMaterial::Multibase {
693 public_key_multibase: multibase_encoded.clone(),
694 },
695 };
696
697 let did_doc = crate::did::DIDDoc {
699 id: did.clone(),
700 verification_method: vec![verification_method],
701 authentication: vec![vm_id],
702 key_agreement: Vec::new(),
703 assertion_method: Vec::new(),
704 capability_invocation: Vec::new(),
705 capability_delegation: Vec::new(),
706 service: Vec::new(),
707 };
708
709 GeneratedKey {
711 key_type: crate::did::KeyType::P256,
712 did: did.clone(),
713 public_key,
714 private_key: private_key.to_vec(),
715 did_doc,
716 }
717 }
718 crate::did::KeyType::Secp256k1 => {
719 if private_key.len() != 32 {
720 return Err(Error::Validation(format!(
721 "Invalid Secp256k1 private key length: {}, expected 32 bytes",
722 private_key.len()
723 )));
724 }
725
726 let signing_key = match k256::ecdsa::SigningKey::from_slice(private_key) {
728 Ok(key) => key,
729 Err(e) => {
730 return Err(Error::Cryptography(format!(
731 "Failed to create Secp256k1 signing key: {:?}",
732 e
733 )))
734 }
735 };
736
737 let public_key = signing_key
739 .verifying_key()
740 .to_encoded_point(false)
741 .to_bytes()
742 .to_vec();
743
744 let mut prefixed_key = vec![0xe7, 0x01];
747 prefixed_key.extend_from_slice(&public_key);
748
749 let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
751 let did = format!("did:key:{}", multibase_encoded);
752
753 let vm_id = format!("{}#{}", did, multibase_encoded);
755
756 let verification_method = VerificationMethod {
758 id: vm_id.clone(),
759 type_: VerificationMethodType::EcdsaSecp256k1VerificationKey2019,
760 controller: did.clone(),
761 verification_material: VerificationMaterial::Multibase {
762 public_key_multibase: multibase_encoded.clone(),
763 },
764 };
765
766 let did_doc = crate::did::DIDDoc {
768 id: did.clone(),
769 verification_method: vec![verification_method],
770 authentication: vec![vm_id],
771 key_agreement: Vec::new(),
772 assertion_method: Vec::new(),
773 capability_invocation: Vec::new(),
774 capability_delegation: Vec::new(),
775 service: Vec::new(),
776 };
777
778 GeneratedKey {
780 key_type: crate::did::KeyType::Secp256k1,
781 did: did.clone(),
782 public_key,
783 private_key: private_key.to_vec(),
784 did_doc,
785 }
786 }
787 };
788
789 let did_generator = DIDKeyGenerator::new();
791 let _secret = did_generator.create_secret_from_key(&generated_key);
792
793 key_manager.add_key(&generated_key)?;
795
796 let config = AgentConfig::new(generated_key.did.clone()).with_debug(debug);
798
799 #[cfg(all(not(target_arch = "wasm32"), test))]
801 {
802 let resolver = Arc::new(crate::did::MultiResolver::default());
804 let agent = Self::new_with_resolver(config, Arc::new(key_manager), resolver);
805 Ok((agent, generated_key.did))
806 }
807
808 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
809 {
810 let agent = Self::new(config, Arc::new(key_manager));
811 Ok((agent, generated_key.did))
812 }
813
814 #[cfg(target_arch = "wasm32")]
815 {
816 let agent = Self::new(config, Arc::new(key_manager));
817 Ok((agent, generated_key.did))
818 }
819 }
820
821 async fn process_message_internal(&self, message: PlainMessage) -> Result<()> {
823 println!(
826 "Processing message: {} of type {}",
827 message.id, message.type_
828 );
829
830 Ok(())
838 }
839
840 #[cfg(not(target_arch = "wasm32"))]
855 fn determine_security_mode<T: TapMessageBody>(&self) -> SecurityMode {
856 if let Some(ref mode) = self.config.security_mode {
858 if mode.to_uppercase() == "AUTHCRYPT" {
859 return SecurityMode::AuthCrypt;
860 } else {
861 return SecurityMode::Signed;
863 }
864 }
865
866 let message_type = T::message_type();
868 if message_type == crate::message::PRESENTATION_MESSAGE_TYPE {
869 SecurityMode::AuthCrypt
870 } else {
871 SecurityMode::Signed
872 }
873 }
874
875 pub async fn get_signing_kid(&self) -> Result<String> {
879 let did = &self.config.agent_did;
880
881 if let Ok(agent_key) = self.key_manager.get_generated_key(did) {
883 if let Some(auth_method_id) = agent_key.did_doc.authentication.first() {
885 return Ok(auth_method_id.clone());
886 }
887
888 if let Some(vm) = agent_key.did_doc.verification_method.first() {
890 return Ok(vm.id.clone());
891 }
892 }
893
894 if did.starts_with("did:key:") {
896 let multibase = did.strip_prefix("did:key:").unwrap_or("");
897 Ok(format!("{}#{}", did, multibase))
898 } else if did.starts_with("did:web:") {
899 Ok(format!("{}#keys-1", did))
900 } else {
901 Ok(format!("{}#key-1", did))
902 }
903 }
904
905 pub async fn get_encryption_kid(&self, recipient_did: &str) -> Result<String> {
909 if recipient_did == self.config.agent_did {
910 if let Ok(agent_key) = self.key_manager.get_generated_key(recipient_did) {
912 if let Some(agreement_method_id) = agent_key.did_doc.key_agreement.first() {
914 return Ok(agreement_method_id.clone());
915 }
916
917 if let Some(auth_method_id) = agent_key.did_doc.authentication.first() {
919 return Ok(auth_method_id.clone());
920 }
921
922 if let Some(vm) = agent_key.did_doc.verification_method.first() {
924 return Ok(vm.id.clone());
925 }
926 }
927
928 return self.get_signing_kid().await;
930 }
931
932 #[cfg(all(not(target_arch = "wasm32"), test))]
934 if let Some(resolver) = &self.resolver {
935 if let Ok(Some(did_doc)) = resolver.resolve(recipient_did).await {
936 if let Some(agreement_method_id) = did_doc.key_agreement.first() {
938 return Ok(agreement_method_id.clone());
939 }
940
941 if let Some(auth_method_id) = did_doc.authentication.first() {
943 return Ok(auth_method_id.clone());
944 }
945
946 if let Some(vm) = did_doc.verification_method.first() {
948 return Ok(vm.id.clone());
949 }
950 }
951 }
952
953 if recipient_did.starts_with("did:key:") {
955 let multibase = recipient_did.strip_prefix("did:key:").unwrap_or("");
956 Ok(format!("{}#{}", recipient_did, multibase))
957 } else if recipient_did.starts_with("did:web:") {
958 Ok(format!("{}#keys-1", recipient_did))
959 } else {
960 Ok(format!("{}#key-1", recipient_did))
961 }
962 }
963
964 #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
973 pub async fn send_to_endpoint(&self, packed_message: &str, endpoint: &str) -> Result<u16> {
974 let client = self
976 .http_client
977 .as_ref()
978 .ok_or_else(|| Error::Networking("HTTP client not available".to_string()))?;
979
980 let response = client
982 .post(endpoint)
983 .header("Content-Type", "application/didcomm-encrypted+json")
984 .body(packed_message.to_string())
985 .send()
986 .await
987 .map_err(|e| Error::Networking(format!("Failed to send message to endpoint: {}", e)))?;
988
989 let status = response.status().as_u16();
991
992 println!("Message sent to endpoint {}, status: {}", endpoint, status);
994
995 Ok(status)
996 }
997
998 #[cfg(any(not(feature = "native"), target_arch = "wasm32"))]
999 pub async fn send_to_endpoint(&self, _packed_message: &str, _endpoint: &str) -> Result<u16> {
1000 Err(crate::error::Error::NotImplemented(
1002 "HTTP client not available".to_string(),
1003 ))
1004 }
1005
1006 pub async fn create_enhanced_agent(
1008 agent_id: String,
1009 policies: Vec<String>,
1010 metadata: std::collections::HashMap<String, String>,
1011 save_to_storage: bool,
1012 ) -> Result<(Self, String)> {
1013 Self::create_enhanced_agent_with_path(agent_id, policies, metadata, save_to_storage, None)
1014 .await
1015 }
1016
1017 pub async fn create_enhanced_agent_with_path(
1019 agent_id: String,
1020 policies: Vec<String>,
1021 metadata: std::collections::HashMap<String, String>,
1022 save_to_storage: bool,
1023 storage_path: Option<PathBuf>,
1024 ) -> Result<(Self, String)> {
1025 use crate::did::{DIDGenerationOptions, KeyType};
1026 use crate::storage::KeyStorage;
1027
1028 let key_manager = AgentKeyManager::new();
1030 let generated_key = key_manager.generate_key_without_save(DIDGenerationOptions {
1031 key_type: KeyType::Ed25519,
1032 })?;
1033
1034 let config = AgentConfig::new(agent_id.clone()).with_debug(true);
1036
1037 let mut custom_generated_key = generated_key.clone();
1040 custom_generated_key.did = agent_id.clone();
1041 key_manager.add_key_without_save(&custom_generated_key)?;
1042
1043 #[cfg(all(not(target_arch = "wasm32"), test))]
1045 let agent = {
1046 let resolver = Arc::new(crate::did::MultiResolver::default());
1047 Self::new_with_resolver(config, Arc::new(key_manager), resolver)
1048 };
1049
1050 #[cfg(all(not(target_arch = "wasm32"), not(test)))]
1051 let agent = Self::new(config, Arc::new(key_manager));
1052
1053 #[cfg(target_arch = "wasm32")]
1054 let agent = Self::new(config, Arc::new(key_manager));
1055
1056 if save_to_storage {
1057 let mut key_storage = if let Some(path) = &storage_path {
1059 KeyStorage::load_from_path(path)?
1060 } else {
1061 KeyStorage::load_default()?
1062 };
1063
1064 let mut stored_key = KeyStorage::from_generated_key(&custom_generated_key);
1066 stored_key.label = format!("agent-{}", agent_id.split(':').last().unwrap_or("agent"));
1067
1068 key_storage.add_key(stored_key);
1069
1070 if let Some(path) = &storage_path {
1071 key_storage.save_to_path(path)?;
1072 } else {
1073 key_storage.save_default()?;
1074 }
1075
1076 key_storage.create_agent_directory(&agent_id, &policies, &metadata)?;
1078 }
1079
1080 Ok((agent, agent_id))
1081 }
1082
1083 pub async fn load_enhanced_agent(
1085 did: &str,
1086 ) -> Result<(Self, Vec<String>, std::collections::HashMap<String, String>)> {
1087 use crate::storage::KeyStorage;
1088
1089 let key_storage = KeyStorage::load_default()?;
1091
1092 let agent = if key_storage.keys.contains_key(did) {
1094 Self::from_stored_keys(Some(did.to_string()), true).await?
1096 } else {
1097 let (mut agent, _) = Self::from_ephemeral_key().await?;
1100 agent.config.agent_did = did.to_string();
1101 agent
1102 };
1103
1104 let policies = key_storage.load_agent_policies(did).unwrap_or_default();
1106 let metadata = key_storage.load_agent_metadata(did).unwrap_or_default();
1107
1108 Ok((agent, policies, metadata))
1109 }
1110
1111 pub fn list_enhanced_agents() -> Result<Vec<EnhancedAgentInfo>> {
1113 Self::list_enhanced_agents_with_path(None)
1114 }
1115
1116 pub fn list_enhanced_agents_with_path(
1118 storage_path: Option<PathBuf>,
1119 ) -> Result<Vec<EnhancedAgentInfo>> {
1120 use crate::storage::KeyStorage;
1121 use std::fs;
1122
1123 let key_storage = if let Some(path) = &storage_path {
1124 KeyStorage::load_from_path(path)?
1125 } else {
1126 KeyStorage::load_default()?
1127 };
1128 let mut agents = Vec::new();
1129
1130 let tap_dir = if let Some(path) = &storage_path {
1132 path.parent()
1134 .ok_or_else(|| Error::Storage("Invalid storage path".to_string()))?
1135 .to_path_buf()
1136 } else {
1137 let home = dirs::home_dir()
1138 .ok_or_else(|| Error::Storage("Could not determine home directory".to_string()))?;
1139 home.join(crate::storage::DEFAULT_TAP_DIR)
1140 };
1141
1142 if !tap_dir.exists() {
1143 return Ok(agents);
1144 }
1145
1146 for entry in fs::read_dir(&tap_dir)? {
1148 let entry = entry?;
1149 let path = entry.path();
1150
1151 if path.is_dir() {
1152 let dir_name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
1153
1154 if dir_name == "keys.json" || dir_name.is_empty() {
1156 continue;
1157 }
1158
1159 let did = dir_name.replace('_', ":");
1161
1162 let policies = key_storage.load_agent_policies(&did).unwrap_or_default();
1164 let metadata = key_storage.load_agent_metadata(&did).unwrap_or_default();
1165
1166 if !policies.is_empty() || !metadata.is_empty() {
1168 agents.push((did, policies, metadata));
1169 }
1170 }
1171 }
1172
1173 Ok(agents)
1174 }
1175}
1176
1177#[async_trait]
1178#[cfg(not(target_arch = "wasm32"))]
1179impl crate::agent::Agent for TapAgent {
1180 fn get_agent_did(&self) -> &str {
1181 &self.config.agent_did
1182 }
1183
1184 async fn get_service_endpoint(&self, to: &str) -> Result<Option<String>> {
1185 if to.starts_with("http://") || to.starts_with("https://") {
1187 return Ok(Some(to.to_string()));
1188 }
1189
1190 if to.starts_with("did:") {
1192 #[cfg(test)]
1197 if let Some(resolver) = self.resolver.as_ref() {
1198 if let Ok(Some(did_doc)) = resolver.resolve(to).await {
1199 if let Some(service) = did_doc
1201 .service
1202 .iter()
1203 .find(|s| s.type_ == "DIDCommMessaging")
1204 {
1205 return Ok(Some(service.service_endpoint.clone()));
1206 }
1207
1208 if let Some(service) = did_doc.service.iter().find(|s| s.type_ == "Web") {
1210 return Ok(Some(service.service_endpoint.clone()));
1211 }
1212
1213 if !did_doc.service.is_empty() {
1215 return Ok(Some(did_doc.service[0].service_endpoint.clone()));
1217 }
1218 }
1219 }
1220
1221 return Ok(Some(format!(
1223 "https://example.com/did/{}",
1224 to.replace(":", "_")
1225 )));
1226 }
1227
1228 Ok(None)
1230 }
1231
1232 async fn send_message<
1233 T: TapMessageBody + serde::Serialize + Send + Sync + std::fmt::Debug + 'static,
1234 >(
1235 &self,
1236 message: &T,
1237 to: Vec<&str>,
1238 deliver: bool,
1239 ) -> Result<(String, Vec<DeliveryResult>)> {
1240 if to.is_empty() {
1241 return Err(Error::Validation("No recipients specified".to_string()));
1242 }
1243
1244 println!("\n==== SENDING TAP MESSAGE ====");
1246 println!("Message Type: {}", T::message_type());
1247 println!("Recipients: {:?}", to);
1248
1249 let plain_message =
1251 message.to_didcomm_with_route(self.get_agent_did(), to.iter().copied())?;
1252
1253 let security_mode = self.determine_security_mode::<T>();
1255 println!("Security Mode: {:?}", security_mode);
1256
1257 for recipient in &to {
1259 if let Ok(Some(endpoint)) = self.get_service_endpoint(recipient).await {
1260 println!("Found service endpoint for {}: {}", recipient, endpoint);
1261 }
1262 }
1263
1264 let sender_kid = self.get_signing_kid().await?;
1266 let recipient_kid = if to.len() == 1 && security_mode == SecurityMode::AuthCrypt {
1267 Some(self.get_encryption_kid(to[0]).await?)
1268 } else {
1269 None
1270 };
1271
1272 let pack_options = PackOptions {
1274 security_mode,
1275 sender_kid: Some(sender_kid),
1276 recipient_kid,
1277 };
1278
1279 let packed = plain_message.pack(&*self.key_manager, pack_options).await?;
1281
1282 println!("--- PACKED MESSAGE ---");
1284 println!(
1285 "{}",
1286 serde_json::from_str::<Value>(&packed)
1287 .map(|v| serde_json::to_string_pretty(&v).unwrap_or(packed.clone()))
1288 .unwrap_or(packed.clone())
1289 );
1290 println!("=====================");
1291
1292 if !deliver {
1294 return Ok((packed, Vec::new()));
1295 }
1296
1297 let mut delivery_results = Vec::new();
1299
1300 for recipient in &to {
1301 match self.get_service_endpoint(recipient).await {
1302 Ok(Some(endpoint)) => {
1303 println!("Delivering message to {} at {}", recipient, endpoint);
1304
1305 let message_id = match serde_json::from_str::<Value>(&packed) {
1307 Ok(json) => json
1308 .get("id")
1309 .and_then(|id| id.as_str())
1310 .map(String::from)
1311 .unwrap_or_else(|| "unknown".to_string()),
1312 Err(_) => "unknown".to_string(),
1313 };
1314
1315 match self.send_to_endpoint(&packed, &endpoint).await {
1317 Ok(status) => {
1318 println!(
1319 "✅ Delivered message {} to {} at {}",
1320 message_id, recipient, endpoint
1321 );
1322
1323 delivery_results.push(DeliveryResult {
1324 did: recipient.to_string(),
1325 endpoint: endpoint.clone(),
1326 status: Some(status),
1327 error: None,
1328 });
1329 }
1330 Err(e) => {
1331 let error_msg = format!(
1333 "Failed to deliver message {} to {} at {}: {}",
1334 message_id, recipient, endpoint, e
1335 );
1336 println!("❌ {}", error_msg);
1337
1338 delivery_results.push(DeliveryResult {
1339 did: recipient.to_string(),
1340 endpoint: endpoint.clone(),
1341 status: None,
1342 error: Some(error_msg),
1343 });
1344 }
1345 }
1346 }
1347 Ok(None) => {
1348 println!(
1349 "⚠️ No service endpoint found for {}, skipping delivery",
1350 recipient
1351 );
1352 }
1353 Err(e) => {
1354 let error_msg = format!(
1356 "Failed to resolve service endpoint for {}: {}",
1357 recipient, e
1358 );
1359 println!("❌ {}", error_msg);
1360 }
1361 }
1362 }
1363
1364 Ok((packed, delivery_results))
1365 }
1366
1367 async fn receive_encrypted_message(&self, jwe_value: &Value) -> Result<()> {
1368 println!("\n==== RECEIVING ENCRYPTED MESSAGE ====");
1370 println!("Agent DID: {}", self.get_agent_did());
1371
1372 let jwe: crate::message::Jwe = serde_json::from_value(jwe_value.clone())
1374 .map_err(|e| Error::Serialization(format!("Failed to parse JWE: {}", e)))?;
1375
1376 let our_kid = self.get_signing_kid().await.ok();
1378
1379 let unpack_options = UnpackOptions {
1381 expected_security_mode: SecurityMode::AuthCrypt,
1382 expected_recipient_kid: our_kid,
1383 require_signature: false,
1384 };
1385
1386 let plain_message =
1388 crate::message::Jwe::unpack(&jwe, &*self.key_manager, unpack_options).await?;
1389
1390 self.process_message_internal(plain_message).await
1392 }
1393
1394 async fn receive_plain_message(&self, message: PlainMessage) -> Result<()> {
1395 println!("\n==== RECEIVING PLAIN MESSAGE ====");
1397 println!("Message ID: {}", message.id);
1398 println!("Message Type: {}", message.type_);
1399
1400 self.process_message_internal(message).await
1401 }
1402
1403 async fn receive_message(&self, raw_message: &str) -> Result<PlainMessage> {
1404 println!("\n==== RECEIVING RAW MESSAGE ====");
1406 println!("Agent DID: {}", self.get_agent_did());
1407
1408 let json_value: Value = serde_json::from_str(raw_message)
1410 .map_err(|e| Error::Serialization(format!("Failed to parse message as JSON: {}", e)))?;
1411
1412 let is_encrypted =
1414 json_value.get("protected").is_some() && json_value.get("recipients").is_some();
1415 let is_signed =
1416 json_value.get("payload").is_some() && json_value.get("signatures").is_some();
1417
1418 println!(
1419 "Message type detection: encrypted={}, signed={}",
1420 is_encrypted, is_signed
1421 );
1422
1423 if is_signed {
1424 println!("Detected signed message");
1425 println!("--- SIGNED MESSAGE ---");
1426 println!(
1427 "{}",
1428 serde_json::to_string_pretty(&json_value).unwrap_or(raw_message.to_string())
1429 );
1430 println!("---------------------");
1431
1432 let jws: crate::message::Jws = serde_json::from_value(json_value)
1434 .map_err(|e| Error::Serialization(format!("Failed to parse JWS: {}", e)))?;
1435
1436 #[cfg(test)]
1438 let plain_message = if let Some(resolver) = &self.resolver {
1439 crate::verification::verify_jws(&jws, &**resolver).await?
1440 } else {
1441 let unpack_options = UnpackOptions {
1443 expected_security_mode: SecurityMode::Signed,
1444 expected_recipient_kid: None,
1445 require_signature: true,
1446 };
1447 crate::message::Jws::unpack(&jws, &*self.key_manager, unpack_options).await?
1448 };
1449
1450 #[cfg(not(test))]
1451 let plain_message = {
1452 let unpack_options = UnpackOptions {
1454 expected_security_mode: SecurityMode::Signed,
1455 expected_recipient_kid: None,
1456 require_signature: true,
1457 };
1458 crate::message::Jws::unpack(&jws, &*self.key_manager, unpack_options).await?
1459 };
1460
1461 println!("--- UNPACKED CONTENT ---");
1463 println!(
1464 "{}",
1465 serde_json::to_string_pretty(&plain_message)
1466 .unwrap_or_else(|_| format!("{:?}", plain_message))
1467 );
1468 println!("------------------------");
1469
1470 Ok(plain_message)
1471 } else if is_encrypted {
1472 println!("Detected encrypted message");
1473 println!("--- ENCRYPTED MESSAGE ---");
1474 println!(
1475 "{}",
1476 serde_json::to_string_pretty(&json_value).unwrap_or(raw_message.to_string())
1477 );
1478 println!("---------------------");
1479
1480 let our_kid = self.get_signing_kid().await.ok();
1482
1483 let unpack_options = UnpackOptions {
1485 expected_security_mode: SecurityMode::AuthCrypt,
1486 expected_recipient_kid: our_kid,
1487 require_signature: false,
1488 };
1489
1490 println!("Unpacking with options: {:?}", unpack_options);
1491
1492 let plain_message: PlainMessage =
1494 match String::unpack(&raw_message.to_string(), &*self.key_manager, unpack_options)
1495 .await
1496 {
1497 Ok(msg) => msg,
1498 Err(e) => {
1499 println!("Failed to unpack message: {}", e);
1500 return Err(e);
1501 }
1502 };
1503
1504 println!("--- UNPACKED CONTENT ---");
1506 println!(
1507 "{}",
1508 serde_json::to_string_pretty(&plain_message)
1509 .unwrap_or_else(|_| format!("{:?}", plain_message))
1510 );
1511 println!("------------------------");
1512
1513 Ok(plain_message)
1514 } else {
1515 println!("Detected plain message");
1517 println!("--- PLAIN MESSAGE ---");
1518 println!(
1519 "{}",
1520 serde_json::to_string_pretty(&json_value).unwrap_or(raw_message.to_string())
1521 );
1522 println!("---------------------");
1523
1524 serde_json::from_str::<PlainMessage>(raw_message)
1526 .map_err(|e| Error::Serialization(format!("Failed to parse PlainMessage: {}", e)))
1527 }
1528 }
1529}