commit 44233ecf9f1df49d19b76b95f2429b3b98183e34
parent 4c05d075ac1c0e6a7d51afd2e57760e3960f1784
Author: William Casarin <jb55@jb55.com>
Date: Wed, 18 Feb 2026 10:04:09 -0800
refactor: unify permission publish data into PermissionPublish struct
Extract a shared PermissionPublish struct to replace the duplicated
{perm_id, allowed, message} fields across PermissionResponseResult,
UiActionResult, KeyActionResult, SendActionResult, and
PendingPermResponse. Handlers now return Option<PermissionPublish>,
making it impossible to forget relay publishing for new prompt types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
3 files changed, 40 insertions(+), 166 deletions(-)
diff --git a/crates/notedeck_dave/src/lib.rs b/crates/notedeck_dave/src/lib.rs
@@ -137,7 +137,7 @@ pub struct Dave {
session_state_sub: Option<nostrdb::Subscription>,
/// Permission responses queued for relay publishing (from remote sessions).
/// Built and published in the update loop where AppContext is available.
- pending_perm_responses: Vec<PendingPermResponse>,
+ pending_perm_responses: Vec<PermissionPublish>,
/// Sessions pending deletion state event publication.
/// Populated in delete_session(), drained in the update loop where AppContext is available.
pending_deletions: Vec<DeletedSessionInfo>,
@@ -145,12 +145,7 @@ pub struct Dave {
hostname: String,
}
-/// A permission response queued for relay publishing.
-struct PendingPermResponse {
- perm_id: uuid::Uuid,
- allowed: bool,
- message: Option<String>,
-}
+use update::PermissionPublish;
/// Info captured from a session before deletion, for publishing a "deleted" state event.
struct DeletedSessionInfo {
@@ -1759,16 +1754,8 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
KeyActionResult::SetAutoSteal(new_state) => {
self.auto_steal_focus = new_state;
}
- KeyActionResult::PublishPermissionResponse {
- perm_id,
- allowed,
- message,
- } => {
- self.pending_perm_responses.push(PendingPermResponse {
- perm_id,
- allowed,
- message,
- });
+ KeyActionResult::PublishPermissionResponse(publish) => {
+ self.pending_perm_responses.push(publish);
}
KeyActionResult::None => {}
}
@@ -1780,16 +1767,8 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
SendActionResult::SendMessage => {
self.handle_user_send(ctx, ui);
}
- SendActionResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } => {
- self.pending_perm_responses.push(PendingPermResponse {
- perm_id,
- allowed,
- message,
- });
+ SendActionResult::NeedsRelayPublish(publish) => {
+ self.pending_perm_responses.push(publish);
}
SendActionResult::Handled => {}
}
@@ -1815,16 +1794,8 @@ You are an AI agent for the nostr protocol called Dave, created by Damus. nostr
self.handle_send_action(ctx, ui);
None
}
- UiActionResult::PublishPermissionResponse {
- perm_id,
- allowed,
- message,
- } => {
- self.pending_perm_responses.push(PendingPermResponse {
- perm_id,
- allowed,
- message,
- });
+ UiActionResult::PublishPermissionResponse(publish) => {
+ self.pending_perm_responses.push(publish);
None
}
UiActionResult::Handled => None,
diff --git a/crates/notedeck_dave/src/ui/mod.rs b/crates/notedeck_dave/src/ui/mod.rs
@@ -432,12 +432,8 @@ pub enum KeyActionResult {
CloneAgent,
DeleteSession(SessionId),
SetAutoSteal(bool),
- /// Permission response needs relay publishing (remote session).
- PublishPermissionResponse {
- perm_id: uuid::Uuid,
- allowed: bool,
- message: Option<String>,
- },
+ /// Permission response needs relay publishing.
+ PublishPermissionResponse(update::PermissionPublish),
}
/// Handle a keybinding action.
@@ -465,17 +461,8 @@ pub fn handle_key_action(
if let Some(session) = session_manager.get_active_mut() {
session.focus_requested = true;
}
- if let update::PermissionResponseResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } = result
- {
- return KeyActionResult::PublishPermissionResponse {
- perm_id,
- allowed,
- message,
- };
+ if let Some(publish) = result {
+ return KeyActionResult::PublishPermissionResponse(publish);
}
}
KeyActionResult::None
@@ -492,17 +479,8 @@ pub fn handle_key_action(
if let Some(session) = session_manager.get_active_mut() {
session.focus_requested = true;
}
- if let update::PermissionResponseResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } = result
- {
- return KeyActionResult::PublishPermissionResponse {
- perm_id,
- allowed,
- message,
- };
+ if let Some(publish) = result {
+ return KeyActionResult::PublishPermissionResponse(publish);
}
}
KeyActionResult::None
@@ -591,12 +569,8 @@ pub enum SendActionResult {
Handled,
/// Normal send - caller should send the user message
SendMessage,
- /// Permission response needs relay publishing (remote session).
- NeedsRelayPublish {
- perm_id: uuid::Uuid,
- allowed: bool,
- message: Option<String>,
- },
+ /// Permission response needs relay publishing.
+ NeedsRelayPublish(update::PermissionPublish),
}
/// Handle the Send action, including tentative permission states.
@@ -630,17 +604,8 @@ pub fn handle_send_action(
request_id,
PermissionResponse::Allow { message },
);
- if let update::PermissionResponseResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } = result
- {
- return SendActionResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- };
+ if let Some(publish) = result {
+ return SendActionResult::NeedsRelayPublish(publish);
}
}
SendActionResult::Handled
@@ -660,17 +625,8 @@ pub fn handle_send_action(
request_id,
PermissionResponse::Deny { reason },
);
- if let update::PermissionResponseResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } = result
- {
- return SendActionResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- };
+ if let Some(publish) = result {
+ return SendActionResult::NeedsRelayPublish(publish);
}
}
SendActionResult::Handled
@@ -687,12 +643,8 @@ pub enum UiActionResult {
SendAction,
/// Return an AppAction
AppAction(notedeck::AppAction),
- /// Permission response needs relay publishing (remote session).
- PublishPermissionResponse {
- perm_id: uuid::Uuid,
- allowed: bool,
- message: Option<String>,
- },
+ /// Permission response needs relay publishing.
+ PublishPermissionResponse(update::PermissionPublish),
}
/// Handle a UI action from DaveUi.
@@ -725,23 +677,8 @@ pub fn handle_ui_action(
DaveAction::PermissionResponse {
request_id,
response,
- } => {
- let result = update::handle_permission_response(session_manager, request_id, response);
- if let update::PermissionResponseResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } = result
- {
- UiActionResult::PublishPermissionResponse {
- perm_id,
- allowed,
- message,
- }
- } else {
- UiActionResult::Handled
- }
- }
+ } => update::handle_permission_response(session_manager, request_id, response)
+ .map_or(UiActionResult::Handled, UiActionResult::PublishPermissionResponse),
DaveAction::Interrupt => {
update::execute_interrupt(session_manager, backend, ctx);
UiActionResult::Handled
@@ -757,24 +694,8 @@ pub fn handle_ui_action(
DaveAction::QuestionResponse {
request_id,
answers,
- } => {
- let result =
- update::handle_question_response(session_manager, request_id, answers);
- if let update::PermissionResponseResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } = result
- {
- UiActionResult::PublishPermissionResponse {
- perm_id,
- allowed,
- message,
- }
- } else {
- UiActionResult::Handled
- }
- }
+ } => update::handle_question_response(session_manager, request_id, answers)
+ .map_or(UiActionResult::Handled, UiActionResult::PublishPermissionResponse),
DaveAction::ExitPlanMode {
request_id,
approved,
@@ -795,20 +716,7 @@ pub fn handle_ui_action(
},
)
};
- if let update::PermissionResponseResult::NeedsRelayPublish {
- perm_id,
- allowed,
- message,
- } = result
- {
- UiActionResult::PublishPermissionResponse {
- perm_id,
- allowed,
- message,
- }
- } else {
- UiActionResult::Handled
- }
+ result.map_or(UiActionResult::Handled, UiActionResult::PublishPermissionResponse)
}
}
}
diff --git a/crates/notedeck_dave/src/update.rs b/crates/notedeck_dave/src/update.rs
@@ -185,16 +185,11 @@ pub fn has_pending_exit_plan_mode(session_manager: &SessionManager) -> bool {
pending_permission_tool_name(session_manager) == Some("ExitPlanMode")
}
-/// Result of handling a permission response.
-pub enum PermissionResponseResult {
- /// Handled locally (oneshot sent to Claude process).
- Local,
- /// Needs relay publishing (remote session, no local process).
- NeedsRelayPublish {
- perm_id: uuid::Uuid,
- allowed: bool,
- message: Option<String>,
- },
+/// Data needed to publish a permission response to relays.
+pub struct PermissionPublish {
+ pub perm_id: uuid::Uuid,
+ pub allowed: bool,
+ pub message: Option<String>,
}
/// Handle a permission response (from UI button or keybinding).
@@ -202,9 +197,9 @@ pub fn handle_permission_response(
session_manager: &mut SessionManager,
request_id: uuid::Uuid,
response: PermissionResponse,
-) -> PermissionResponseResult {
+) -> Option<PermissionPublish> {
let Some(session) = session_manager.get_active_mut() else {
- return PermissionResponseResult::Local;
+ return None;
};
let is_remote = session.is_remote();
@@ -264,11 +259,11 @@ pub fn handle_permission_response(
}
}
- PermissionResponseResult::NeedsRelayPublish {
+ Some(PermissionPublish {
perm_id: request_id,
allowed,
message,
- }
+ })
}
/// Handle a user's response to an AskUserQuestion tool call.
@@ -276,9 +271,9 @@ pub fn handle_question_response(
session_manager: &mut SessionManager,
request_id: uuid::Uuid,
answers: Vec<QuestionAnswer>,
-) -> PermissionResponseResult {
+) -> Option<PermissionPublish> {
let Some(session) = session_manager.get_active_mut() else {
- return PermissionResponseResult::Local;
+ return None;
};
let is_remote = session.is_remote();
@@ -401,11 +396,11 @@ pub fn handle_question_response(
}
}
- PermissionResponseResult::NeedsRelayPublish {
+ Some(PermissionPublish {
perm_id: request_id,
allowed: true,
message: Some(formatted_response),
- }
+ })
}
// =============================================================================