tap_cli/commands/
delivery.rs1use crate::error::{Error, Result};
2use crate::output::{print_success, OutputFormat};
3use crate::tap_integration::TapIntegration;
4use clap::Subcommand;
5use serde::Serialize;
6
7#[derive(Subcommand, Debug)]
8pub enum DeliveryCommands {
9 List {
11 #[arg(long, group = "filter")]
13 recipient: Option<String>,
14 #[arg(long, group = "filter")]
16 message: Option<String>,
17 #[arg(long, group = "filter")]
19 thread: Option<String>,
20 #[arg(long)]
22 agent_did: Option<String>,
23 #[arg(long, default_value = "50")]
25 limit: u32,
26 #[arg(long, default_value = "0")]
28 offset: u32,
29 },
30}
31
32#[derive(Debug, Serialize)]
33struct DeliveryInfo {
34 id: i64,
35 message_id: String,
36 recipient_did: String,
37 status: String,
38 retry_count: i32,
39 delivery_type: String,
40 created_at: String,
41 updated_at: String,
42 delivered_at: Option<String>,
43 error_message: Option<String>,
44}
45
46#[derive(Debug, Serialize)]
47struct DeliveryListResponse {
48 deliveries: Vec<DeliveryInfo>,
49 total: usize,
50}
51
52fn to_delivery_info(d: &tap_node::storage::models::Delivery) -> DeliveryInfo {
53 DeliveryInfo {
54 id: d.id,
55 message_id: d.message_id.clone(),
56 recipient_did: d.recipient_did.clone(),
57 status: format!("{:?}", d.status),
58 retry_count: d.retry_count,
59 delivery_type: format!("{:?}", d.delivery_type),
60 created_at: d.created_at.clone(),
61 updated_at: d.updated_at.clone(),
62 delivered_at: d.delivered_at.clone(),
63 error_message: d.error_message.clone(),
64 }
65}
66
67pub async fn handle(
68 cmd: &DeliveryCommands,
69 format: OutputFormat,
70 default_agent_did: &str,
71 tap_integration: &TapIntegration,
72) -> Result<()> {
73 match cmd {
74 DeliveryCommands::List {
75 recipient,
76 message,
77 thread,
78 agent_did,
79 limit,
80 offset,
81 } => {
82 let effective_did = agent_did.as_deref().unwrap_or(default_agent_did);
83 let storage = tap_integration.storage_for_agent(effective_did).await?;
84
85 let deliveries = if let Some(recipient) = recipient {
86 storage
87 .get_deliveries_by_recipient(recipient, *limit, *offset)
88 .await?
89 } else if let Some(message_id) = message {
90 storage.get_deliveries_for_message(message_id).await?
91 } else if let Some(thread_id) = thread {
92 storage
93 .get_deliveries_for_thread(thread_id, *limit, *offset)
94 .await?
95 } else {
96 return Err(Error::invalid_parameter(
97 "One of --recipient, --message, or --thread is required",
98 ));
99 };
100
101 let delivery_infos: Vec<DeliveryInfo> =
102 deliveries.iter().map(to_delivery_info).collect();
103
104 let response = DeliveryListResponse {
105 total: delivery_infos.len(),
106 deliveries: delivery_infos,
107 };
108 print_success(format, &response);
109 Ok(())
110 }
111 }
112}