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}