Skip to main content

agentic_workflow/intelligence/
collective.rs

1use std::collections::HashMap;
2
3use chrono::Utc;
4use uuid::Uuid;
5use serde::Serialize;
6
7/// Workflow collective — community sharing of workflow patterns.
8pub struct CollectiveEngine {
9    shared_items: HashMap<String, CollectiveItem>,
10}
11
12#[derive(Debug, Clone, Serialize)]
13pub struct CollectiveItem {
14    pub id: String,
15    pub name: String,
16    pub description: String,
17    pub workflow_definition: serde_json::Value,
18    pub author: String,
19    pub tags: Vec<String>,
20    pub rating: f64,
21    pub rating_count: u32,
22    pub download_count: u64,
23    pub shared_at: chrono::DateTime<chrono::Utc>,
24    pub privacy_verified: bool,
25}
26
27impl CollectiveEngine {
28    pub fn new() -> Self {
29        Self {
30            shared_items: HashMap::new(),
31        }
32    }
33
34    /// Share a workflow with the collective.
35    pub fn share(
36        &mut self,
37        name: &str,
38        description: &str,
39        workflow_definition: serde_json::Value,
40        author: &str,
41        tags: Vec<String>,
42    ) -> String {
43        let id = Uuid::new_v4().to_string();
44        let item = CollectiveItem {
45            id: id.clone(),
46            name: name.to_string(),
47            description: description.to_string(),
48            workflow_definition,
49            author: author.to_string(),
50            tags,
51            rating: 0.0,
52            rating_count: 0,
53            download_count: 0,
54            shared_at: Utc::now(),
55            privacy_verified: false,
56        };
57
58        self.shared_items.insert(id.clone(), item);
59        id
60    }
61
62    /// Search community workflows.
63    pub fn search(&self, query: &str) -> Vec<&CollectiveItem> {
64        let query_lower = query.to_lowercase();
65        self.shared_items
66            .values()
67            .filter(|item| {
68                item.name.to_lowercase().contains(&query_lower)
69                    || item.description.to_lowercase().contains(&query_lower)
70                    || item.tags.iter().any(|t| t.to_lowercase().contains(&query_lower))
71            })
72            .collect()
73    }
74
75    /// Get a collective item.
76    pub fn get(&self, id: &str) -> Option<&CollectiveItem> {
77        self.shared_items.get(id)
78    }
79
80    /// Apply (download) a community workflow.
81    pub fn apply(&mut self, id: &str) -> Option<serde_json::Value> {
82        if let Some(item) = self.shared_items.get_mut(id) {
83            item.download_count += 1;
84            Some(item.workflow_definition.clone())
85        } else {
86            None
87        }
88    }
89
90    /// Rate a community workflow.
91    pub fn rate(&mut self, id: &str, rating: f64) -> bool {
92        if let Some(item) = self.shared_items.get_mut(id) {
93            let total = item.rating * item.rating_count as f64 + rating;
94            item.rating_count += 1;
95            item.rating = total / item.rating_count as f64;
96            true
97        } else {
98            false
99        }
100    }
101
102    /// Verify no private data in a shared workflow.
103    pub fn verify_privacy(&mut self, id: &str) -> bool {
104        if let Some(item) = self.shared_items.get_mut(id) {
105            // Privacy check: ensure no secrets, tokens, or PII in definition
106            let def_str = item.workflow_definition.to_string().to_lowercase();
107            let suspicious = ["password", "secret", "token", "api_key", "private_key"];
108            let clean = !suspicious.iter().any(|s| def_str.contains(s));
109            item.privacy_verified = clean;
110            clean
111        } else {
112            false
113        }
114    }
115
116    /// List all shared items.
117    pub fn list_all(&self) -> Vec<&CollectiveItem> {
118        self.shared_items.values().collect()
119    }
120}
121
122impl Default for CollectiveEngine {
123    fn default() -> Self {
124        Self::new()
125    }
126}