tap_agent/
agent.rs

1use crate::agent_key_manager::{AgentKeyManager, AgentKeyManagerBuilder};
2use crate::config::AgentConfig;
3#[cfg(all(not(target_arch = "wasm32"), test))]
4use crate::did::SyncDIDResolver; // Import SyncDIDResolver trait
5use crate::error::{Error, Result};
6use crate::key_manager::KeyManager; // Add KeyManager trait
7#[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
24/// Type alias for enhanced agent information: (DID, policies, metadata)
25pub type EnhancedAgentInfo = (
26    String,
27    Vec<String>,
28    std::collections::HashMap<String, String>,
29);
30
31/// Result of a message delivery attempt
32#[derive(Debug, Clone)]
33pub struct DeliveryResult {
34    /// The DID of the recipient
35    pub did: String,
36    /// The service endpoint URL that was used for delivery
37    pub endpoint: String,
38    /// HTTP status code if the delivery was successful
39    pub status: Option<u16>,
40    /// Error message if the delivery failed
41    pub error: Option<String>,
42}
43
44/// The Agent trait defines the interface for all TAP agents
45///
46/// This trait supports both standalone agent usage and integration with TAP Node.
47/// The different receive methods are designed for different usage patterns:
48///
49/// # Usage Patterns
50///
51/// ## Node Integration
52/// - [`receive_encrypted_message`]: Called by TAP Node for encrypted messages
53/// - [`receive_plain_message`]: Called by TAP Node for verified/decrypted messages
54///
55/// ## Standalone Usage
56/// - [`receive_message`]: Handles any message type (plain, signed, encrypted)
57///
58/// ## Message Sending
59/// - [`send_message`]: Sends messages to recipients with optional delivery
60///
61/// # Examples
62///
63/// ```rust,no_run
64/// use tap_agent::{Agent, TapAgent};
65/// use tap_msg::didcomm::PlainMessage;
66///
67/// async fn process_encrypted_message(agent: &TapAgent, jwe_json: &serde_json::Value) {
68///     // This would typically be called by TAP Node
69///     if let Err(e) = agent.receive_encrypted_message(jwe_json).await {
70///         eprintln!("Failed to process encrypted message: {}", e);
71///     }
72/// }
73/// ```
74#[cfg(not(target_arch = "wasm32"))]
75#[async_trait]
76#[cfg(not(target_arch = "wasm32"))]
77pub trait Agent {
78    /// Gets the agent's DID
79    fn get_agent_did(&self) -> &str;
80
81    /// Gets the service endpoint URL for a recipient
82    ///
83    /// This method resolves how to reach a given recipient, which could be:
84    /// - A direct URL if `to` is already a URL
85    /// - A DID resolution if `to` is a DID
86    async fn get_service_endpoint(&self, to: &str) -> Result<Option<String>>;
87
88    /// Sends a message to one or more recipients
89    ///
90    /// # Parameters
91    /// - `message`: The message to send (must implement TapMessageBody)
92    /// - `to`: List of recipient DIDs or URLs
93    /// - `deliver`: Whether to actually deliver the message or just pack it
94    ///
95    /// # Returns
96    /// - Packed message string
97    /// - Vector of delivery results (empty if deliver=false)
98    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    /// Receives an encrypted message (decrypt and process)
108    ///
109    /// This method is typically called by TAP Node when routing encrypted
110    /// messages to agents. The agent should:
111    /// 1. Parse the JWE from the JSON value
112    /// 2. Attempt to decrypt using its private keys
113    /// 3. Process the resulting PlainMessage
114    ///
115    /// # Parameters
116    /// - `jwe_value`: JSON representation of the encrypted message (JWE)
117    async fn receive_encrypted_message(&self, jwe_value: &Value) -> Result<()>;
118
119    /// Receives a plain message (already verified/decrypted)
120    ///
121    /// This method is called by TAP Node after signature verification
122    /// or by other agents after decryption. The message is ready for
123    /// business logic processing.
124    ///
125    /// # Parameters
126    /// - `message`: The verified/decrypted PlainMessage
127    async fn receive_plain_message(&self, message: PlainMessage) -> Result<()>;
128
129    /// Receives a raw message (for standalone usage - handles any message type)
130    ///
131    /// This method handles the complete message processing pipeline for
132    /// standalone agent usage. It can process:
133    /// - Plain messages (passed through)
134    /// - Signed messages (signature verified)
135    /// - Encrypted messages (decrypted)
136    ///
137    /// # Parameters
138    /// - `raw_message`: JSON string of any message type
139    ///
140    /// # Returns
141    /// - The processed PlainMessage
142    async fn receive_message(&self, raw_message: &str) -> Result<PlainMessage>;
143
144    /// Send a strongly-typed message
145    ///
146    /// # Parameters
147    /// - `message`: The typed message to send
148    /// - `deliver`: Whether to actually deliver the message
149    ///
150    /// # Returns
151    /// - Packed message string
152    /// - Vector of delivery results (empty if deliver=false)
153    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        // Convert to plain message and use existing send infrastructure
159        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        // Extract the body and send using the existing method
163        let body = serde_json::from_value::<T>(plain_message.body)?;
164        self.send_message(&body, to_vec, deliver).await
165    }
166
167    /// Send a message with MessageContext support for automatic routing
168    ///
169    /// This method uses MessageContext to automatically extract participants
170    /// and routing hints for improved message delivery.
171    ///
172    /// # Parameters
173    /// - `message`: The message body that implements both TapMessageBody and MessageContext
174    /// - `deliver`: Whether to actually deliver the message
175    ///
176    /// # Returns
177    /// - Packed message string
178    /// - Vector of delivery results (empty if deliver=false)
179    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        // Extract participants using MessageContext
193        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()) // Don't send to self
198            .collect();
199
200        // Get routing hints for enhanced delivery
201        let _routing_hints = message.routing_hints();
202
203        // TODO: Use routing_hints to optimize delivery
204        // For now, just use the standard send_message method
205        self.send_message(message, recipients, deliver).await
206    }
207
208    /// Send a typed message with automatic context routing
209    ///
210    /// # Parameters
211    /// - `message`: The typed message with MessageContext support
212    /// - `deliver`: Whether to actually deliver the message
213    ///
214    /// # Returns
215    /// - Packed message string
216    /// - Vector of delivery results (empty if deliver=false)
217    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        // Use the enhanced participant extraction
231        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()) // Don't send to self
236            .collect();
237
238        // Get routing hints
239        let _routing_hints = message.routing_hints();
240
241        // Extract the body and send using the context-aware method
242        let body = message.body;
243        self.send_with_context(&body, deliver).await
244    }
245
246    /// Receive and parse a typed message
247    ///
248    /// # Parameters
249    /// - `raw_message`: The raw message string
250    ///
251    /// # Type Parameters
252    /// - `T`: The expected message body type
253    ///
254    /// # Returns
255    /// - The typed message if parsing succeeds
256    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/// A simplified Agent trait for WASM with relaxed bounds
265#[cfg(target_arch = "wasm32")]
266pub trait WasmAgent {
267    /// Gets the agent's DID
268    fn get_agent_did(&self) -> &str;
269
270    /// Pack a message for delivery
271    fn pack_message<T: TapMessageBody + serde::Serialize>(&self, message: &T) -> Result<String>;
272
273    /// Unpack a received message
274    fn unpack_message<T: TapMessageBody + DeserializeOwned>(
275        &self,
276        packed_message: &str,
277    ) -> Result<T>;
278}
279
280/// TapAgent implementation using the AgentKeyManager for cryptographic operations.
281#[derive(Debug, Clone)]
282pub struct TapAgent {
283    /// Configuration for the agent
284    pub config: AgentConfig,
285    /// Key Manager for cryptographic operations
286    key_manager: Arc<AgentKeyManager>,
287    /// DID Resolver for resolving DIDs to service endpoints
288    #[cfg(all(not(target_arch = "wasm32"), test))]
289    resolver: Option<Arc<dyn SyncDIDResolver>>,
290    /// HTTP client for sending requests
291    #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
292    http_client: Option<Client>,
293}
294
295impl TapAgent {
296    /// Returns a reference to the agent's key manager
297    pub fn key_manager(&self) -> &Arc<AgentKeyManager> {
298        &self.key_manager
299    }
300
301    /// Creates a new TapAgent with the given configuration and AgentKeyManager
302    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    /// Creates a new TapAgent with the given configuration, key manager, and DID resolver
352    #[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    /// Creates a new TapAgent with an ephemeral key
382    ///
383    /// This function generates a new DID key for temporary use.
384    /// The key is not persisted to storage and will be lost when the agent is dropped.
385    ///
386    /// # Returns
387    ///
388    /// A tuple containing the TapAgent and the DID that was generated
389    pub async fn from_ephemeral_key() -> crate::error::Result<(Self, String)> {
390        use crate::did::{DIDGenerationOptions, KeyType};
391
392        // Create a key manager
393        let key_manager = AgentKeyManager::new();
394
395        // Generate a key
396        let key = key_manager.generate_key(DIDGenerationOptions {
397            key_type: KeyType::Ed25519,
398        })?;
399
400        // Create a config with the new DID
401        let config = AgentConfig::new(key.did.clone()).with_debug(true);
402
403        // Create the agent
404        #[cfg(all(not(target_arch = "wasm32"), test))]
405        {
406            // Create a default resolver
407            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    /// Creates a new TapAgent from stored keys
426    ///
427    /// This function uses the AgentKeyManagerBuilder to load keys from storage
428    ///
429    /// # Arguments
430    ///
431    /// * `did` - Optional DID to use. If None, the default DID from storage is used.
432    /// * `debug` - Whether to enable debug mode
433    ///
434    /// # Returns
435    ///
436    /// A Result containing either the created agent or an error if no keys are available
437    pub async fn from_stored_keys(did: Option<String>, debug: bool) -> Result<Self> {
438        use crate::storage::KeyStorage;
439
440        // Load keys from storage
441        let key_manager_builder = AgentKeyManagerBuilder::new().load_from_default_storage();
442        let key_manager = key_manager_builder.build()?;
443
444        // Get the DIDs available in the key manager
445        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        // Get the DID to use
453        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            // Try to get the default DID from storage
463            let storage = KeyStorage::load_default()?;
464            storage.default_did.unwrap_or_else(|| dids[0].clone())
465        };
466
467        // Create agent config
468        let config = AgentConfig::new(agent_did).with_debug(debug);
469
470        // Create the agent
471        #[cfg(all(not(target_arch = "wasm32"), test))]
472        {
473            // Create a default resolver
474            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    /// Creates a new TapAgent from an existing private key
494    ///
495    /// This function creates a new TapAgent using a provided private key,
496    /// which can be useful for integrating with external key management systems
497    /// or when keys are generated outside the TAP agent.
498    ///
499    /// # Arguments
500    ///
501    /// * `private_key` - The private key bytes
502    /// * `key_type` - The type of key (Ed25519, P256, or Secp256k1)
503    /// * `debug` - Whether to enable debug mode
504    ///
505    /// # Returns
506    ///
507    /// A Result containing either the created agent or an error
508    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        // Create a key manager to hold our key
519        let key_manager = AgentKeyManager::new();
520
521        // Generate the appropriate key and DID based on the key type
522        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                // For Ed25519, we need to derive the public key from the private key
532                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                // Get the public key
538                let verifying_key = ed25519_dalek::VerifyingKey::from(&signing_key);
539                let public_key = verifying_key.to_bytes().to_vec();
540
541                // Create did:key identifier
542                // Multicodec prefix for Ed25519: 0xed01
543                let mut prefixed_key = vec![0xed, 0x01];
544                prefixed_key.extend_from_slice(&public_key);
545
546                // Encode the key with multibase (base58btc with 'z' prefix)
547                let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
548                let did = format!("did:key:{}", multibase_encoded);
549
550                // Create the verification method ID
551                let vm_id = format!("{}#{}", did, multibase_encoded);
552
553                // Create the verification method
554                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                // Create X25519 key for key agreement - Implement the ed25519_to_x25519 conversion directly
564                let x25519_method_and_agreement = {
565                    // Only Ed25519 public keys must be exactly 32 bytes
566                    if public_key.len() != 32 {
567                        None
568                    } else {
569                        // Try to create a CompressedEdwardsY from the bytes
570                        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                        // Try to decompress to get the Edwards point
580                        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                        // Convert to Montgomery form
590                        let montgomery_point = edwards_point.to_montgomery();
591
592                        // Get the raw bytes representation of the X25519 key
593                        let x25519_key = montgomery_point.to_bytes();
594
595                        // Prefix for X25519: 0xEC01
596                        let mut x25519_prefixed = vec![0xEC, 0x01];
597                        x25519_prefixed.extend_from_slice(&x25519_key);
598
599                        // Encode the prefixed X25519 key with multibase
600                        let x25519_multibase = encode(Base::Base58Btc, &x25519_prefixed);
601
602                        // Create the X25519 verification method ID
603                        let x25519_vm_id = format!("{}#{}", did, x25519_multibase);
604
605                        // Create the X25519 verification method
606                        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                // Build verification methods array
620                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                // Create the DID document
629                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                // Create a GeneratedKey with all necessary fields
641                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                // For P-256, create a signing key from the private key
658                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                // Get the public key in uncompressed form
669                let public_key = signing_key
670                    .verifying_key()
671                    .to_encoded_point(false)
672                    .to_bytes()
673                    .to_vec();
674
675                // Create did:key identifier
676                // Multicodec prefix for P-256: 0x1200
677                let mut prefixed_key = vec![0x12, 0x00];
678                prefixed_key.extend_from_slice(&public_key);
679
680                // Encode the key with multibase (base58btc with 'z' prefix)
681                let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
682                let did = format!("did:key:{}", multibase_encoded);
683
684                // Create the verification method ID
685                let vm_id = format!("{}#{}", did, multibase_encoded);
686
687                // Create the verification method
688                let verification_method = VerificationMethod {
689                    id: vm_id.clone(),
690                    type_: VerificationMethodType::EcdsaSecp256k1VerificationKey2019, // Using the available type
691                    controller: did.clone(),
692                    verification_material: VerificationMaterial::Multibase {
693                        public_key_multibase: multibase_encoded.clone(),
694                    },
695                };
696
697                // Create the DID document
698                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                // Create a GeneratedKey with all necessary fields
710                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                // For Secp256k1, create a signing key from the private key
727                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                // Get the public key in uncompressed form
738                let public_key = signing_key
739                    .verifying_key()
740                    .to_encoded_point(false)
741                    .to_bytes()
742                    .to_vec();
743
744                // Create did:key identifier
745                // Multicodec prefix for Secp256k1: 0xe701
746                let mut prefixed_key = vec![0xe7, 0x01];
747                prefixed_key.extend_from_slice(&public_key);
748
749                // Encode the key with multibase (base58btc with 'z' prefix)
750                let multibase_encoded = encode(Base::Base58Btc, &prefixed_key);
751                let did = format!("did:key:{}", multibase_encoded);
752
753                // Create the verification method ID
754                let vm_id = format!("{}#{}", did, multibase_encoded);
755
756                // Create the verification method
757                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                // Create the DID document
767                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                // Create a GeneratedKey with all necessary fields
779                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        // Create secret from the generated key and use it to add to the key manager
790        let did_generator = DIDKeyGenerator::new();
791        let _secret = did_generator.create_secret_from_key(&generated_key);
792
793        // Add the key to the key manager
794        key_manager.add_key(&generated_key)?;
795
796        // Create a config with the new DID
797        let config = AgentConfig::new(generated_key.did.clone()).with_debug(debug);
798
799        // Create the agent
800        #[cfg(all(not(target_arch = "wasm32"), test))]
801        {
802            // Create a default resolver
803            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    /// Internal method to process a PlainMessage
822    async fn process_message_internal(&self, message: PlainMessage) -> Result<()> {
823        // This is where actual message processing logic would go
824        // For now, just log that we processed it
825        println!(
826            "Processing message: {} of type {}",
827            message.id, message.type_
828        );
829
830        // TODO: Add actual message processing logic here
831        // This could include:
832        // - Validating the message against policies
833        // - Updating internal state
834        // - Triggering workflows
835        // - Generating responses
836
837        Ok(())
838    }
839
840    /// Determine the appropriate security mode for a message type
841    ///
842    /// This method implements TAP protocol rules for which security modes
843    /// should be used with different message types:
844    /// - Presentation messages use authenticated encryption (AuthCrypt)
845    /// - All other messages use digital signatures (Signed)
846    ///
847    /// If security_mode is specified in the agent config, that takes precedence.
848    ///
849    /// # Parameters
850    /// * `message_type` - The type of the message
851    ///
852    /// # Returns
853    /// The appropriate SecurityMode for the message type
854    #[cfg(not(target_arch = "wasm32"))]
855    fn determine_security_mode<T: TapMessageBody>(&self) -> SecurityMode {
856        // If security mode is explicitly configured, use that
857        if let Some(ref mode) = self.config.security_mode {
858            if mode.to_uppercase() == "AUTHCRYPT" {
859                return SecurityMode::AuthCrypt;
860            } else {
861                // Default to Signed for any other value
862                return SecurityMode::Signed;
863            }
864        }
865
866        // Otherwise use type-based rules
867        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    /// Get the signing key ID for this agent
876    ///
877    /// Resolves the DID document and returns the first authentication verification method ID
878    pub async fn get_signing_kid(&self) -> Result<String> {
879        let did = &self.config.agent_did;
880
881        // Try to get the DID document from our key manager first
882        if let Ok(agent_key) = self.key_manager.get_generated_key(did) {
883            // Get the first authentication method from the DID document
884            if let Some(auth_method_id) = agent_key.did_doc.authentication.first() {
885                return Ok(auth_method_id.clone());
886            }
887
888            // Fallback to first verification method
889            if let Some(vm) = agent_key.did_doc.verification_method.first() {
890                return Ok(vm.id.clone());
891            }
892        }
893
894        // Fallback to guessing based on DID method (for backward compatibility)
895        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    /// Get the encryption key ID for a recipient
906    ///
907    /// Resolves the DID document and returns the appropriate key agreement method ID
908    pub async fn get_encryption_kid(&self, recipient_did: &str) -> Result<String> {
909        if recipient_did == self.config.agent_did {
910            // If asking for our own encryption key, get it from our DID document
911            if let Ok(agent_key) = self.key_manager.get_generated_key(recipient_did) {
912                // Look for key agreement methods first
913                if let Some(agreement_method_id) = agent_key.did_doc.key_agreement.first() {
914                    return Ok(agreement_method_id.clone());
915                }
916
917                // Fallback to authentication method (for keys that do both)
918                if let Some(auth_method_id) = agent_key.did_doc.authentication.first() {
919                    return Ok(auth_method_id.clone());
920                }
921
922                // Fallback to first verification method
923                if let Some(vm) = agent_key.did_doc.verification_method.first() {
924                    return Ok(vm.id.clone());
925                }
926            }
927
928            // Final fallback to signing key
929            return self.get_signing_kid().await;
930        }
931
932        // For external recipients, try to resolve their DID document
933        #[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                // Look for key agreement methods first
937                if let Some(agreement_method_id) = did_doc.key_agreement.first() {
938                    return Ok(agreement_method_id.clone());
939                }
940
941                // Fallback to authentication method
942                if let Some(auth_method_id) = did_doc.authentication.first() {
943                    return Ok(auth_method_id.clone());
944                }
945
946                // Fallback to first verification method
947                if let Some(vm) = did_doc.verification_method.first() {
948                    return Ok(vm.id.clone());
949                }
950            }
951        }
952
953        // Fallback to guessing based on DID method (for backward compatibility)
954        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    /// Send a message to a specific endpoint
965    ///
966    /// # Parameters
967    /// * `packed_message` - The packed message to send
968    /// * `endpoint` - The endpoint URL to send the message to
969    ///
970    /// # Returns
971    /// The HTTP response status code, or error if the request failed
972    #[cfg(all(feature = "native", not(target_arch = "wasm32")))]
973    pub async fn send_to_endpoint(&self, packed_message: &str, endpoint: &str) -> Result<u16> {
974        // Get HTTP client
975        let client = self
976            .http_client
977            .as_ref()
978            .ok_or_else(|| Error::Networking("HTTP client not available".to_string()))?;
979
980        // Send the message to the endpoint via HTTP POST
981        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        // Get the status code
990        let status = response.status().as_u16();
991
992        // Log the response status
993        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        // Feature not enabled or WASM doesn't have http_client
1001        Err(crate::error::Error::NotImplemented(
1002            "HTTP client not available".to_string(),
1003        ))
1004    }
1005
1006    /// Create an agent with enhanced configuration (policies and metadata)
1007    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    /// Create an agent with enhanced configuration (policies and metadata) with custom storage path
1018    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        // Create a key manager and generate a key without saving to storage
1029        let key_manager = AgentKeyManager::new();
1030        let generated_key = key_manager.generate_key_without_save(DIDGenerationOptions {
1031            key_type: KeyType::Ed25519,
1032        })?;
1033
1034        // Create a config with the provided agent ID
1035        let config = AgentConfig::new(agent_id.clone()).with_debug(true);
1036
1037        // Add the generated key to the key manager with the custom DID
1038        // Use add_key_without_save to prevent automatic storage write
1039        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        // Create the agent
1044        #[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            // Save to key storage
1058            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            // Convert the generated key to a stored key
1065            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            // Create agent directory with policies and metadata
1077            key_storage.create_agent_directory(&agent_id, &policies, &metadata)?;
1078        }
1079
1080        Ok((agent, agent_id))
1081    }
1082
1083    /// Load an enhanced agent from storage with policies and metadata
1084    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        // Load key storage
1090        let key_storage = KeyStorage::load_default()?;
1091
1092        // Check if the key exists in storage
1093        let agent = if key_storage.keys.contains_key(did) {
1094            // Load agent from stored keys
1095            Self::from_stored_keys(Some(did.to_string()), true).await?
1096        } else {
1097            // If key doesn't exist in storage, create an ephemeral agent
1098            // This is for test scenarios where agents are created but not persisted
1099            let (mut agent, _) = Self::from_ephemeral_key().await?;
1100            agent.config.agent_did = did.to_string();
1101            agent
1102        };
1103
1104        // Load policies and metadata from agent directory
1105        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    /// List all enhanced agents with their policies and metadata
1112    pub fn list_enhanced_agents() -> Result<Vec<EnhancedAgentInfo>> {
1113        Self::list_enhanced_agents_with_path(None)
1114    }
1115
1116    /// List all enhanced agents with their policies and metadata with custom storage path
1117    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        // Get TAP directory
1131        let tap_dir = if let Some(path) = &storage_path {
1132            // For custom paths, the tap directory is the parent of the keys.json file
1133            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        // Scan for agent directories
1147        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                // Skip known non-agent directories
1155                if dir_name == "keys.json" || dir_name.is_empty() {
1156                    continue;
1157                }
1158
1159                // Convert sanitized DID back to original format
1160                let did = dir_name.replace('_', ":");
1161
1162                // Try to load policies and metadata
1163                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                // Only include if there are policies or metadata (indicating an enhanced agent)
1167                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 it's a URL, return it directly
1186        if to.starts_with("http://") || to.starts_with("https://") {
1187            return Ok(Some(to.to_string()));
1188        }
1189
1190        // If it's a DID, try to find a service endpoint using the resolver
1191        if to.starts_with("did:") {
1192            // Use the DID resolver from the AgentKeyManager to get the service endpoints
1193            // For now, we'll use a simple approach that looks for DIDCommMessaging or Web service types
1194
1195            // For testing purposes, attempt to check if TapAgent has a resolver field
1196            #[cfg(test)]
1197            if let Some(resolver) = self.resolver.as_ref() {
1198                if let Ok(Some(did_doc)) = resolver.resolve(to).await {
1199                    // Look for services of type DIDCommMessaging first
1200                    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                    // Then try Web type
1209                    if let Some(service) = did_doc.service.iter().find(|s| s.type_ == "Web") {
1210                        return Ok(Some(service.service_endpoint.clone()));
1211                    }
1212
1213                    // No matching service found in DID doc
1214                    if !did_doc.service.is_empty() {
1215                        // Use the first service as fallback
1216                        return Ok(Some(did_doc.service[0].service_endpoint.clone()));
1217                    }
1218                }
1219            }
1220
1221            // Fallback to a placeholder URL if no resolver is available or no service found
1222            return Ok(Some(format!(
1223                "https://example.com/did/{}",
1224                to.replace(":", "_")
1225            )));
1226        }
1227
1228        // No service endpoint found
1229        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        // Log the plaintext message
1245        println!("\n==== SENDING TAP MESSAGE ====");
1246        println!("Message Type: {}", T::message_type());
1247        println!("Recipients: {:?}", to);
1248
1249        // Convert the TapMessageBody to a PlainMessage with explicit routing
1250        let plain_message =
1251            message.to_didcomm_with_route(self.get_agent_did(), to.iter().copied())?;
1252
1253        // Determine the appropriate security mode
1254        let security_mode = self.determine_security_mode::<T>();
1255        println!("Security Mode: {:?}", security_mode);
1256
1257        // For each recipient, look up service endpoint before sending
1258        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        // Get the appropriate key IDs
1265        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        // Create pack options for the plaintext message
1273        let pack_options = PackOptions {
1274            security_mode,
1275            sender_kid: Some(sender_kid),
1276            recipient_kid,
1277        };
1278
1279        // Pack the plain message using the Packable trait
1280        let packed = plain_message.pack(&*self.key_manager, pack_options).await?;
1281
1282        // Log the packed message
1283        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 delivery is not requested, just return the packed message
1293        if !deliver {
1294            return Ok((packed, Vec::new()));
1295        }
1296
1297        // Try to deliver the message to each recipient's service endpoint
1298        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                    // Extract message ID for logging
1306                    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                    // Attempt to deliver the message
1316                    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                            // Log error but don't fail
1332                            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                    // Log error but don't fail
1355                    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        // Log the received encrypted message
1369        println!("\n==== RECEIVING ENCRYPTED MESSAGE ====");
1370        println!("Agent DID: {}", self.get_agent_did());
1371
1372        // Parse as JWE
1373        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        // Get our encryption key ID
1377        let our_kid = self.get_signing_kid().await.ok();
1378
1379        // Create unpack options
1380        let unpack_options = UnpackOptions {
1381            expected_security_mode: SecurityMode::AuthCrypt,
1382            expected_recipient_kid: our_kid,
1383            require_signature: false,
1384        };
1385
1386        // Decrypt the message
1387        let plain_message =
1388            crate::message::Jwe::unpack(&jwe, &*self.key_manager, unpack_options).await?;
1389
1390        // Process the decrypted message
1391        self.process_message_internal(plain_message).await
1392    }
1393
1394    async fn receive_plain_message(&self, message: PlainMessage) -> Result<()> {
1395        // Process already verified/decrypted message
1396        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        // Log the received raw message
1405        println!("\n==== RECEIVING RAW MESSAGE ====");
1406        println!("Agent DID: {}", self.get_agent_did());
1407
1408        // First try to parse as JSON to determine message type
1409        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        // Check if it's an encrypted message (JWE) or signed message (JWS)
1413        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            // Parse as JWS
1433            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            // Verify using our resolver
1437            #[cfg(test)]
1438            let plain_message = if let Some(resolver) = &self.resolver {
1439                crate::verification::verify_jws(&jws, &**resolver).await?
1440            } else {
1441                // Fallback to unpacking with key manager for test compatibility
1442                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                // In production, we need a resolver - for now use unpacking
1453                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            // Log the unpacked message
1462            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            // Get our encryption key ID
1481            let our_kid = self.get_signing_kid().await.ok();
1482
1483            // Create unpack options
1484            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            // Unpack the message
1493            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            // Log the unpacked message
1505            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            // It's already a plain message
1516            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            // Parse directly as PlainMessage
1525            serde_json::from_str::<PlainMessage>(raw_message)
1526                .map_err(|e| Error::Serialization(format!("Failed to parse PlainMessage: {}", e)))
1527        }
1528    }
1529}