j_agent/permission/
queue.rs1use std::collections::VecDeque;
12use std::sync::{Arc, Condvar, Mutex};
13use std::time::Duration;
14
15const AGENT_PERM_TIMEOUT_SECS: u64 = 60;
17
18#[derive(Clone, Debug, PartialEq)]
20pub enum AgentType {
21 Main,
23 Teammate,
25 SubAgent,
27}
28
29pub struct PendingAgentPerm {
32 pub agent_type: AgentType,
34 pub name: String,
36 pub tool_name: String,
38 pub confirm_msg: String,
40 decision: Arc<(Mutex<Option<bool>>, Condvar)>,
42}
43
44impl PendingAgentPerm {
45 pub fn new(
46 agent_type: AgentType,
47 name: String,
48 tool_name: String,
49 confirm_msg: String,
50 ) -> Arc<Self> {
51 Arc::new(Self {
52 agent_type,
53 name,
54 tool_name,
55 confirm_msg,
56 decision: Arc::new((Mutex::new(None), Condvar::new())),
57 })
58 }
59
60 pub fn title(&self) -> String {
62 match &self.agent_type {
63 AgentType::Main => " 权限请求 [Main] ".to_string(),
64 AgentType::Teammate => format!(" 权限请求 [{}] ", self.name),
65 AgentType::SubAgent => format!(" SubAgent 权限请求 [{}] ", self.name),
66 }
67 }
68
69 pub fn wait_for_decision(&self, timeout_secs: u64) -> bool {
71 let (lock, cvar) = &*self.decision;
72 let guard = lock.lock().unwrap_or_else(|e| e.into_inner());
73 let (guard, _timed_out) = cvar
74 .wait_timeout_while(guard, Duration::from_secs(timeout_secs), |d| d.is_none())
75 .unwrap_or_else(|e| e.into_inner());
76 guard.unwrap_or(false)
77 }
78
79 pub fn resolve(&self, approved: bool) {
81 let (lock, cvar) = &*self.decision;
82 let mut d = lock.lock().unwrap_or_else(|e| e.into_inner());
83 *d = Some(approved);
84 cvar.notify_one();
85 }
86}
87
88pub struct PermissionQueue {
90 pub(crate) pending: Mutex<VecDeque<Arc<PendingAgentPerm>>>,
91}
92
93impl Default for PermissionQueue {
94 fn default() -> Self {
95 Self::new()
96 }
97}
98
99impl PermissionQueue {
100 pub fn new() -> Self {
101 Self {
102 pending: Mutex::new(VecDeque::new()),
103 }
104 }
105
106 pub fn request_blocking(&self, req: Arc<PendingAgentPerm>) -> bool {
109 {
110 let mut q = self.pending.lock().unwrap_or_else(|e| e.into_inner());
111 q.push_back(Arc::clone(&req));
112 }
113 req.wait_for_decision(AGENT_PERM_TIMEOUT_SECS)
114 }
115
116 pub fn pop_pending(&self) -> Option<Arc<PendingAgentPerm>> {
118 self.pending
119 .lock()
120 .unwrap_or_else(|e| e.into_inner())
121 .pop_front()
122 }
123
124 pub fn deny_all(&self) {
126 let mut q = self.pending.lock().unwrap_or_else(|e| e.into_inner());
127 for req in q.drain(..) {
128 req.resolve(false);
129 }
130 }
131}
132
133#[cfg(test)]
134mod tests;