Skip to main content

trace_weft/
hitl.rs

1use serde_json::Value;
2use std::collections::HashMap;
3use std::sync::Mutex;
4use tokio::sync::oneshot;
5
6lazy_static::lazy_static! {
7    // Stores pending approvals: Span ID -> Sender to resume execution
8    static ref PENDING_APPROVALS: Mutex<HashMap<String, oneshot::Sender<HitlResponse>>> = Mutex::new(HashMap::new());
9}
10
11#[derive(Debug, Clone)]
12pub enum HitlResponse {
13    Approved(Value),  // The potentially modified payload
14    Rejected(String), // Reason for rejection
15}
16
17/// Registers a pending approval and returns a receiver to await the user's response.
18pub fn register_approval(span_id: String) -> oneshot::Receiver<HitlResponse> {
19    let (tx, rx) = oneshot::channel();
20    if let Ok(mut pending) = PENDING_APPROVALS.lock() {
21        pending.insert(span_id, tx);
22    }
23    rx
24}
25
26/// Resolves a pending approval with the given response.
27pub fn resolve_approval(span_id: &str, response: HitlResponse) -> Result<(), String> {
28    let tx = {
29        if let Ok(mut pending) = PENDING_APPROVALS.lock() {
30            pending.remove(span_id)
31        } else {
32            None
33        }
34    };
35
36    if let Some(tx) = tx {
37        tx.send(response)
38            .map_err(|_| "Failed to send HITL response".to_string())
39    } else {
40        Err(format!("No pending approval found for span {}", span_id))
41    }
42}
43
44/// Returns a list of all currently pending span IDs.
45pub fn get_pending_approvals() -> Vec<String> {
46    if let Ok(pending) = PENDING_APPROVALS.lock() {
47        pending.keys().cloned().collect()
48    } else {
49        vec![]
50    }
51}