Skip to main content

tap_cli/commands/
communication.rs

1use crate::error::{Error, Result};
2use crate::output::{print_success, OutputFormat};
3use crate::tap_integration::TapIntegration;
4use clap::Subcommand;
5use serde::Serialize;
6use tap_msg::message::tap_message_trait::TapMessageBody;
7use tap_msg::message::{BasicMessage, TrustPing};
8use tracing::debug;
9
10#[derive(Subcommand, Debug)]
11pub enum CommunicationCommands {
12    /// Send a trust ping to verify connectivity
13    Ping {
14        /// Recipient DID
15        #[arg(long)]
16        recipient: String,
17    },
18    /// Send a basic text message
19    Message {
20        /// Recipient DID
21        #[arg(long)]
22        recipient: String,
23        /// Message content
24        #[arg(long)]
25        content: String,
26    },
27}
28
29#[derive(Debug, Serialize)]
30struct PingResponse {
31    message_id: String,
32    recipient: String,
33    status: String,
34    timestamp: String,
35}
36
37#[derive(Debug, Serialize)]
38struct MessageResponse {
39    message_id: String,
40    recipient: String,
41    status: String,
42    timestamp: String,
43}
44
45pub async fn handle(
46    cmd: &CommunicationCommands,
47    format: OutputFormat,
48    agent_did: &str,
49    tap_integration: &TapIntegration,
50) -> Result<()> {
51    match cmd {
52        CommunicationCommands::Ping { recipient } => {
53            handle_ping(agent_did, recipient, format, tap_integration).await
54        }
55        CommunicationCommands::Message { recipient, content } => {
56            handle_message(agent_did, recipient, content, format, tap_integration).await
57        }
58    }
59}
60
61async fn handle_ping(
62    agent_did: &str,
63    recipient: &str,
64    format: OutputFormat,
65    tap_integration: &TapIntegration,
66) -> Result<()> {
67    let ping = TrustPing::new();
68
69    let mut didcomm_message = ping
70        .to_didcomm(agent_did)
71        .map_err(|e| Error::command_failed(format!("Failed to create DIDComm message: {}", e)))?;
72
73    didcomm_message.to = vec![recipient.to_string()];
74
75    debug!("Sending trust ping from {} to {}", agent_did, recipient);
76
77    tap_integration
78        .node()
79        .send_message(agent_did.to_string(), didcomm_message.clone())
80        .await
81        .map_err(|e| Error::command_failed(format!("Failed to send ping: {}", e)))?;
82
83    let response = PingResponse {
84        message_id: didcomm_message.id,
85        recipient: recipient.to_string(),
86        status: "sent".to_string(),
87        timestamp: chrono::Utc::now().to_rfc3339(),
88    };
89    print_success(format, &response);
90    Ok(())
91}
92
93async fn handle_message(
94    agent_did: &str,
95    recipient: &str,
96    content: &str,
97    format: OutputFormat,
98    tap_integration: &TapIntegration,
99) -> Result<()> {
100    let message = BasicMessage::new(content.to_string());
101
102    let mut didcomm_message = message
103        .to_didcomm(agent_did)
104        .map_err(|e| Error::command_failed(format!("Failed to create DIDComm message: {}", e)))?;
105
106    didcomm_message.to = vec![recipient.to_string()];
107
108    debug!("Sending basic message from {} to {}", agent_did, recipient);
109
110    tap_integration
111        .node()
112        .send_message(agent_did.to_string(), didcomm_message.clone())
113        .await
114        .map_err(|e| Error::command_failed(format!("Failed to send message: {}", e)))?;
115
116    let response = MessageResponse {
117        message_id: didcomm_message.id,
118        recipient: recipient.to_string(),
119        status: "sent".to_string(),
120        timestamp: chrono::Utc::now().to_rfc3339(),
121    };
122    print_success(format, &response);
123    Ok(())
124}