Skip to main content

tap_cli/
tap_integration.rs

1use crate::error::{Error, Result};
2use std::path::PathBuf;
3use std::sync::Arc;
4use tap_agent::TapAgent;
5use tap_node::{NodeConfig, TapNode};
6use tracing::{debug, error, info};
7
8/// TAP ecosystem integration - thin wrapper around TapNode
9pub struct TapIntegration {
10    node: Arc<TapNode>,
11    storage_path: Option<PathBuf>,
12}
13
14impl TapIntegration {
15    /// Create new TAP integration using TapNode with agent registration
16    pub async fn new(
17        agent_did: Option<&str>,
18        tap_root: Option<&str>,
19        agent: Option<Arc<TapAgent>>,
20    ) -> Result<Self> {
21        let mut config = NodeConfig::default();
22
23        if let Some(did) = agent_did {
24            config.agent_did = Some(did.to_string());
25        }
26
27        if let Some(root) = tap_root {
28            config.tap_root = Some(PathBuf::from(root));
29        }
30
31        config.enable_message_logging = true;
32        config.log_message_content = true;
33
34        let mut node = TapNode::new(config);
35
36        node.init_storage().await.map_err(|e| {
37            Error::configuration(format!("Failed to initialize TAP node storage: {}", e))
38        })?;
39
40        info!("Initialized TAP integration with DID-based storage");
41
42        let node_arc = Arc::new(node);
43
44        if let Some(agent) = agent {
45            node_arc
46                .register_agent(agent)
47                .await
48                .map_err(|e| Error::configuration(format!("Failed to register agent: {}", e)))?;
49            info!("Registered primary agent with TAP Node");
50        }
51
52        // Load and register all additional agents from storage
53        match tap_agent::storage::KeyStorage::load_default() {
54            Ok(storage) => {
55                let stored_dids: Vec<String> = storage.keys.keys().cloned().collect();
56                info!("Found {} total keys in storage", stored_dids.len());
57
58                for stored_did in &stored_dids {
59                    if agent_did.is_some_and(|did| stored_did == did) {
60                        continue;
61                    }
62
63                    info!("Registering additional agent: {}", stored_did);
64                    match TapAgent::from_stored_keys(Some(stored_did.clone()), true).await {
65                        Ok(additional_agent) => {
66                            let additional_agent_arc = Arc::new(additional_agent);
67                            if let Err(e) = node_arc.register_agent(additional_agent_arc).await {
68                                error!("Failed to register additional agent {}: {}", stored_did, e);
69                            } else {
70                                info!("Successfully registered additional agent: {}", stored_did);
71                            }
72                        }
73                        Err(e) => {
74                            error!("Failed to load additional agent {}: {}", stored_did, e);
75                        }
76                    }
77                }
78            }
79            Err(e) => {
80                debug!("Could not load additional keys from storage: {}", e);
81            }
82        }
83
84        Ok(Self {
85            node: node_arc,
86            storage_path: None,
87        })
88    }
89
90    /// Create new TAP integration for testing with custom paths
91    #[allow(dead_code)]
92    pub async fn new_for_testing(tap_root: Option<&str>, agent_did: &str) -> Result<Self> {
93        let mut config = NodeConfig::default();
94
95        if let Some(root) = tap_root {
96            config.tap_root = Some(PathBuf::from(root));
97        }
98
99        config.agent_did = Some(agent_did.to_string());
100        config.enable_message_logging = true;
101        config.log_message_content = true;
102
103        let mut node = TapNode::new(config);
104        node.init_storage().await.map_err(|e| {
105            Error::configuration(format!("Failed to initialize TAP node storage: {}", e))
106        })?;
107
108        let storage_path = tap_root.map(|root| PathBuf::from(root).join("keys.json"));
109
110        let (test_agent, _) = TapAgent::from_ephemeral_key()
111            .await
112            .map_err(|e| Error::configuration(format!("Failed to create test agent: {}", e)))?;
113
114        let node_arc = Arc::new(node);
115        node_arc
116            .register_agent(Arc::new(test_agent))
117            .await
118            .map_err(|e| Error::configuration(format!("Failed to register test agent: {}", e)))?;
119
120        Ok(Self {
121            node: node_arc,
122            storage_path,
123        })
124    }
125
126    pub fn node(&self) -> &Arc<TapNode> {
127        &self.node
128    }
129
130    #[allow(dead_code)]
131    pub fn storage_path(&self) -> Option<&PathBuf> {
132        self.storage_path.as_ref()
133    }
134
135    pub async fn storage_for_agent(
136        &self,
137        agent_did: &str,
138    ) -> Result<Arc<tap_node::storage::Storage>> {
139        if let Some(storage_manager) = self.node.agent_storage_manager() {
140            storage_manager
141                .get_agent_storage(agent_did)
142                .await
143                .map_err(|e| {
144                    Error::configuration(format!(
145                        "Failed to get storage for agent {}: {}",
146                        agent_did, e
147                    ))
148                })
149        } else {
150            Err(Error::configuration(
151                "Agent storage manager not available".to_string(),
152            ))
153        }
154    }
155
156    pub async fn list_agents(&self) -> Result<Vec<AgentInfo>> {
157        let mut agents = Vec::new();
158
159        use tap_agent::storage::KeyStorage;
160        let key_storage = if let Some(ref storage_path) = self.storage_path {
161            KeyStorage::load_from_path(storage_path)
162        } else {
163            KeyStorage::load_default()
164        };
165
166        match key_storage {
167            Ok(storage) => {
168                for (did, stored_key) in &storage.keys {
169                    let mut metadata = std::collections::HashMap::new();
170
171                    if !stored_key.label.is_empty() {
172                        metadata.insert("label".to_string(), stored_key.label.clone());
173                    }
174
175                    for (key, value) in &stored_key.metadata {
176                        metadata.insert(key.clone(), value.clone());
177                    }
178
179                    agents.push(AgentInfo {
180                        id: did.clone(),
181                        label: if stored_key.label.is_empty() {
182                            None
183                        } else {
184                            Some(stored_key.label.clone())
185                        },
186                        metadata,
187                    });
188                }
189            }
190            Err(e) => {
191                debug!("Could not load key storage: {}", e);
192            }
193        }
194
195        // Include any agents only registered in TapNode
196        let node_agent_dids = self.node.list_agents();
197        for did in node_agent_dids {
198            if !agents.iter().any(|a| a.id == did) {
199                agents.push(AgentInfo {
200                    id: did,
201                    label: None,
202                    metadata: std::collections::HashMap::new(),
203                });
204            }
205        }
206
207        Ok(agents)
208    }
209}
210
211#[derive(Debug, Clone, serde::Serialize)]
212pub struct AgentInfo {
213    pub id: String,
214    pub label: Option<String>,
215    pub metadata: std::collections::HashMap<String, String>,
216}