agent_engine/tools/
secret_prompt.rs1use std::sync::{Arc, Mutex};
2
3#[derive(Clone)]
9pub struct SecretPromptHandle {
10 tx: tokio::sync::mpsc::UnboundedSender<SecretPromptRequest>,
11}
12
13impl SecretPromptHandle {
14 pub fn new(tx: tokio::sync::mpsc::UnboundedSender<SecretPromptRequest>) -> Self {
15 Self { tx }
16 }
17
18 pub async fn prompt(&self, title: String, prompt: String) -> Option<String> {
19 let (response_tx, response_rx) = tokio::sync::oneshot::channel();
20 let request = SecretPromptRequest {
21 title,
22 prompt,
23 response_tx,
24 };
25 self.tx.send(request).ok()?;
26 response_rx.await.ok().flatten()
27 }
28}
29
30pub struct SecretPromptRequest {
31 pub title: String,
32 pub prompt: String,
33 pub response_tx: tokio::sync::oneshot::Sender<Option<String>>,
34}
35
36pub struct PendingSecretPrompt {
37 pub title: String,
38 pub prompt: String,
39 pub buffer: String,
40 pub response_tx: tokio::sync::oneshot::Sender<Option<String>>,
41}
42
43pub struct SecretPromptQueue {
44 active: Option<PendingSecretPrompt>,
45 pending: std::collections::VecDeque<SecretPromptRequest>,
46}
47
48impl Default for SecretPromptQueue {
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54impl SecretPromptQueue {
55 pub fn new() -> Self {
56 Self {
57 active: None,
58 pending: std::collections::VecDeque::new(),
59 }
60 }
61
62 pub fn poll_requests(
63 &mut self,
64 rx: &Arc<Mutex<tokio::sync::mpsc::UnboundedReceiver<SecretPromptRequest>>>,
65 ) {
66 if let Ok(mut rx) = rx.lock() {
67 while let Ok(req) = rx.try_recv() {
68 self.pending.push_back(req);
69 }
70 }
71 self.activate_next();
72 }
73
74 fn activate_next(&mut self) {
75 if self.active.is_some() {
76 return;
77 }
78 if let Some(req) = self.pending.pop_front() {
79 self.active = Some(PendingSecretPrompt {
80 title: req.title,
81 prompt: req.prompt,
82 buffer: String::new(),
83 response_tx: req.response_tx,
84 });
85 }
86 }
87
88 pub fn is_active(&self) -> bool {
89 self.active.is_some()
90 }
91
92 pub fn active(&self) -> Option<&PendingSecretPrompt> {
93 self.active.as_ref()
94 }
95
96 pub fn push_char(&mut self, ch: char) {
97 if let Some(active) = self.active.as_mut() {
98 active.buffer.push(ch);
99 }
100 }
101
102 pub fn backspace(&mut self) {
103 if let Some(active) = self.active.as_mut() {
104 active.buffer.pop();
105 }
106 }
107
108 pub fn submit(&mut self) {
109 if let Some(mut active) = self.active.take() {
110 let secret = std::mem::take(&mut active.buffer);
111 let _ = active.response_tx.send(Some(secret));
112 }
113 self.activate_next();
114 }
115
116 pub fn cancel(&mut self) {
117 if let Some(mut active) = self.active.take() {
118 active.buffer.clear();
119 let _ = active.response_tx.send(None);
120 }
121 self.activate_next();
122 }
123}