Skip to main content

supercode_harness/tui/
bridge.rs

1//! P5-4: the data shapes carried across the thread boundary between an
2//! interactive-handler call (blocked on a background/agent thread) and the
3//! render/event-loop's main thread — deliberately just data + a reply
4//! channel, no trait impls, so [`crate::tui::state`] (the pure view-model)
5//! and [`crate::tui::handlers`] (the actual `PermissionsApprovalHandler`/
6//! `McpElicitationHandler` implementations) can both depend on this module
7//! without a circular dependency between them.
8
9use crate::mcp::ElicitationResponse;
10use crate::permissions::ApprovalOutcome;
11
12/// One `Ask`-tier request from the TOP-LEVEL agent's own permissions gate
13/// (P5-1's [`crate::permissions::PermissionsApprovalHandler::ask`]),
14/// waiting on [`Self::reply_tx`] for the TUI's decision. `ask` blocks the
15/// calling thread on the paired `Receiver` until a reply arrives (or the
16/// sending end is dropped — see [`crate::tui::handlers::TuiApprovalHandler`]'s
17/// doc comment for why that's still fail-closed).
18#[derive(Debug)]
19pub struct PendingApprovalRequest {
20    /// The tool being called (`"bash"`, `"write_file"`, …).
21    pub tool: String,
22    /// The canonicalized command/path subject, if any.
23    pub subject: Option<String>,
24    /// The raw, model-supplied arguments.
25    pub raw_args: serde_json::Value,
26    /// Where to send the user's decision.
27    pub reply_tx: std::sync::mpsc::Sender<ApprovalOutcome>,
28}
29
30/// The child-spawn analog of [`PendingApprovalRequest`] (P5-3 §2.2 C6,
31/// closed by [`crate::tui::handlers::TuiChildApprovalHandler`]): additionally
32/// carries which BACKGROUND CHILD raised the request, since a parent may
33/// have several background children in flight at once.
34#[derive(Debug)]
35pub struct PendingChildApproval {
36    /// Which child raised this request.
37    pub child_agent_id: String,
38    /// The tool it tried to call.
39    pub tool: String,
40    /// The canonicalized command/path subject, if any.
41    pub subject: Option<String>,
42    /// The raw, model-supplied arguments.
43    pub raw_args: serde_json::Value,
44    /// Where to send the parent's decision.
45    pub reply_tx: std::sync::mpsc::Sender<ApprovalOutcome>,
46}
47
48/// One server→client `elicitation/create` request
49/// ([`crate::mcp::ElicitationRequest`]), waiting on [`Self::reply_tx`] for
50/// the user's answer. Uses a `tokio::sync::oneshot` (not `std::sync::mpsc`
51/// like the two structs above) because
52/// [`crate::mcp::McpElicitationHandler::handle`] is an ASYNC trait method —
53/// it `.await`s the reply rather than blocking a thread.
54#[derive(Debug)]
55pub struct PendingElicitation {
56    /// The server's human-readable prompt.
57    pub message: String,
58    /// JSON Schema for the requested input shape.
59    pub requested_schema: serde_json::Value,
60    /// Where to send the user's answer.
61    pub reply_tx: tokio::sync::oneshot::Sender<ElicitationResponse>,
62}
63
64/// The OAuth device-code flow's ONE-TIME display push (P5-2's
65/// `run_device_flow`'s `on_prompt` callback) — informational only, no
66/// reply: the device flow polls the token endpoint regardless of whether
67/// the user has acknowledged seeing this, so there is nothing to block on.
68#[derive(Debug, Clone, PartialEq, Eq)]
69pub struct PendingOAuthDisplay {
70    /// The server name this login is for (so a multi-server login session
71    /// is unambiguous in the modal).
72    pub server_name: String,
73    /// Short code the user enters at `verification_uri`.
74    pub user_code: String,
75    /// The URL the user visits.
76    pub verification_uri: String,
77    /// A URL that already embeds `user_code`, if the server provided one.
78    pub verification_uri_complete: Option<String>,
79    /// How long (seconds) the code remains valid.
80    pub expires_in_secs: u64,
81}