mirror of
https://github.com/openai/codex.git
synced 2026-11-04 08:25:29 +00:00
Extract TUI approval request payloads into structs (#33684)
## What changed Give command, permissions, patch, and MCP elicitation approvals dedicated request structs, and update TUI routing and rendering to use the wrapped payloads. GitOrigin-RevId: ffee4058dd27505be2a11de3758ac12bb707b6b8
This commit is contained in:
1 parent
693b8c2ba4
commit
d3fc1950a9
8 files changed
+231
-267
No files matched your search
@@ -23,9 +23,13 @@ use crate::app_server_session::AppServerStartedThread;
|
|||||||
use crate::app_server_session::TurnPermissionsOverride;
|
use crate::app_server_session::TurnPermissionsOverride;
|
||||||
use crate::app_server_session::app_server_rate_limit_snapshots;
|
use crate::app_server_session::app_server_rate_limit_snapshots;
|
||||||
use crate::bottom_pane::AppLinkViewParams;
|
use crate::bottom_pane::AppLinkViewParams;
|
||||||
|
use crate::bottom_pane::ApplyPatchApprovalRequest;
|
||||||
use crate::bottom_pane::ApprovalRequest;
|
use crate::bottom_pane::ApprovalRequest;
|
||||||
|
use crate::bottom_pane::ExecApprovalRequest;
|
||||||
use crate::bottom_pane::FeedbackAudience;
|
use crate::bottom_pane::FeedbackAudience;
|
||||||
|
use crate::bottom_pane::McpElicitationApprovalRequest;
|
||||||
use crate::bottom_pane::McpServerElicitationFormRequest;
|
use crate::bottom_pane::McpServerElicitationFormRequest;
|
||||||
|
use crate::bottom_pane::PermissionsApprovalRequest;
|
||||||
use crate::bottom_pane::SelectionItem;
|
use crate::bottom_pane::SelectionItem;
|
||||||
use crate::bottom_pane::SelectionViewParams;
|
use crate::bottom_pane::SelectionViewParams;
|
||||||
use crate::bottom_pane::popup_consts::standard_popup_hint_line;
|
use crate::bottom_pane::popup_consts::standard_popup_hint_line;
|
||||||
|
|||||||
@@ -2091,18 +2091,18 @@ impl App {
|
|||||||
self.chat_widget.handle_manage_skills_closed();
|
self.chat_widget.handle_manage_skills_closed();
|
||||||
}
|
}
|
||||||
AppEvent::FullScreenApprovalRequest(request) => match request {
|
AppEvent::FullScreenApprovalRequest(request) => match request {
|
||||||
ApprovalRequest::ApplyPatch { cwd, changes, .. } => {
|
ApprovalRequest::ApplyPatch(request) => {
|
||||||
let _ = tui.enter_alt_screen();
|
let _ = tui.enter_alt_screen();
|
||||||
let diff_summary = DiffSummary::new(changes, cwd);
|
let diff_summary = DiffSummary::new(request.changes, request.cwd);
|
||||||
self.overlay = Some(Overlay::new_static_with_renderables(
|
self.overlay = Some(Overlay::new_static_with_renderables(
|
||||||
vec![diff_summary.into()],
|
vec![diff_summary.into()],
|
||||||
"P A T C H".to_string(),
|
"P A T C H".to_string(),
|
||||||
self.keymap.pager.clone(),
|
self.keymap.pager.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ApprovalRequest::Exec { command, .. } => {
|
ApprovalRequest::Exec(request) => {
|
||||||
let _ = tui.enter_alt_screen();
|
let _ = tui.enter_alt_screen();
|
||||||
let full_cmd = strip_bash_lc_and_escape(&command);
|
let full_cmd = strip_bash_lc_and_escape(&request.command);
|
||||||
let full_cmd_lines = highlight_bash_to_lines(&full_cmd);
|
let full_cmd_lines = highlight_bash_to_lines(&full_cmd);
|
||||||
self.overlay = Some(Overlay::new_static_with_lines(
|
self.overlay = Some(Overlay::new_static_with_lines(
|
||||||
full_cmd_lines,
|
full_cmd_lines,
|
||||||
@@ -2110,27 +2110,22 @@ impl App {
|
|||||||
self.keymap.pager.clone(),
|
self.keymap.pager.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ApprovalRequest::Permissions {
|
ApprovalRequest::Permissions(request) => {
|
||||||
environment_id,
|
|
||||||
permissions,
|
|
||||||
reason,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let _ = tui.enter_alt_screen();
|
let _ = tui.enter_alt_screen();
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
if let Some(environment_id) = environment_id {
|
if let Some(environment_id) = request.environment_id {
|
||||||
lines.push(Line::from(vec![
|
lines.push(Line::from(vec![
|
||||||
"Environment: ".into(),
|
"Environment: ".into(),
|
||||||
environment_id.bold(),
|
environment_id.bold(),
|
||||||
]));
|
]));
|
||||||
lines.push(Line::from(""));
|
lines.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(reason) = reason {
|
if let Some(reason) = request.reason {
|
||||||
lines.push(Line::from(vec!["Reason: ".into(), reason.italic()]));
|
lines.push(Line::from(vec!["Reason: ".into(), reason.italic()]));
|
||||||
lines.push(Line::from(""));
|
lines.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(rule_line) =
|
if let Some(rule_line) =
|
||||||
crate::bottom_pane::format_requested_permissions_rule(&permissions)
|
crate::bottom_pane::format_requested_permissions_rule(&request.permissions)
|
||||||
{
|
{
|
||||||
lines.push(Line::from(vec![
|
lines.push(Line::from(vec![
|
||||||
"Permission rule: ".into(),
|
"Permission rule: ".into(),
|
||||||
@@ -2143,16 +2138,12 @@ impl App {
|
|||||||
self.keymap.pager.clone(),
|
self.keymap.pager.clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
ApprovalRequest::McpElicitation {
|
ApprovalRequest::McpElicitation(request) => {
|
||||||
server_name,
|
|
||||||
message,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let _ = tui.enter_alt_screen();
|
let _ = tui.enter_alt_screen();
|
||||||
let paragraph = Paragraph::new(vec![
|
let paragraph = Paragraph::new(vec![
|
||||||
Line::from(vec!["Server: ".into(), server_name.bold()]),
|
Line::from(vec!["Server: ".into(), request.server_name.bold()]),
|
||||||
Line::from(""),
|
Line::from(""),
|
||||||
Line::from(message),
|
Line::from(request.message),
|
||||||
])
|
])
|
||||||
.wrap(Wrap { trim: false });
|
.wrap(Wrap { trim: false });
|
||||||
self.overlay = Some(Overlay::new_static_with_renderables(
|
self.overlay = Some(Overlay::new_static_with_renderables(
|
||||||
|
|||||||
@@ -2543,12 +2543,7 @@ async fn inactive_thread_exec_approval_preserves_context() {
|
|||||||
action: AppServerNetworkPolicyRuleAction::Allow,
|
action: AppServerNetworkPolicyRuleAction::Allow,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
let Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Exec {
|
let Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Exec(approval))) = app
|
||||||
available_decisions,
|
|
||||||
network_approval_context,
|
|
||||||
additional_permissions,
|
|
||||||
..
|
|
||||||
})) = app
|
|
||||||
.interactive_request_for_thread_request(thread_id, &request)
|
.interactive_request_for_thread_request(thread_id, &request)
|
||||||
.await
|
.await
|
||||||
.expect("valid localized paths")
|
.expect("valid localized paths")
|
||||||
@@ -2557,14 +2552,14 @@ async fn inactive_thread_exec_approval_preserves_context() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
network_approval_context,
|
approval.network_approval_context,
|
||||||
Some(AppServerNetworkApprovalContext {
|
Some(AppServerNetworkApprovalContext {
|
||||||
host: "example.com".to_string(),
|
host: "example.com".to_string(),
|
||||||
protocol: AppServerNetworkApprovalProtocol::Socks5Tcp,
|
protocol: AppServerNetworkApprovalProtocol::Socks5Tcp,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
additional_permissions,
|
approval.additional_permissions,
|
||||||
Some(AdditionalPermissionProfile {
|
Some(AdditionalPermissionProfile {
|
||||||
network: Some(AdditionalNetworkPermissions {
|
network: Some(AdditionalNetworkPermissions {
|
||||||
enabled: Some(true),
|
enabled: Some(true),
|
||||||
@@ -2578,7 +2573,7 @@ async fn inactive_thread_exec_approval_preserves_context() {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
available_decisions,
|
approval.available_decisions,
|
||||||
vec![
|
vec![
|
||||||
codex_app_server_protocol::CommandExecutionApprovalDecision::Accept,
|
codex_app_server_protocol::CommandExecutionApprovalDecision::Accept,
|
||||||
codex_app_server_protocol::CommandExecutionApprovalDecision::AcceptForSession,
|
codex_app_server_protocol::CommandExecutionApprovalDecision::AcceptForSession,
|
||||||
@@ -2610,7 +2605,7 @@ async fn inactive_thread_exec_approval_splits_shell_wrapped_command() {
|
|||||||
params.command =
|
params.command =
|
||||||
Some(shlex::try_join(["/bin/zsh", "-lc", script]).expect("round-trippable shell wrapper"));
|
Some(shlex::try_join(["/bin/zsh", "-lc", script]).expect("round-trippable shell wrapper"));
|
||||||
|
|
||||||
let Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Exec { command, .. })) = app
|
let Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Exec(approval))) = app
|
||||||
.interactive_request_for_thread_request(thread_id, &request)
|
.interactive_request_for_thread_request(thread_id, &request)
|
||||||
.await
|
.await
|
||||||
.expect("valid localized paths")
|
.expect("valid localized paths")
|
||||||
@@ -2619,7 +2614,7 @@ async fn inactive_thread_exec_approval_splits_shell_wrapped_command() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
command,
|
approval.command,
|
||||||
vec![
|
vec![
|
||||||
"/bin/zsh".to_string(),
|
"/bin/zsh".to_string(),
|
||||||
"-lc".to_string(),
|
"-lc".to_string(),
|
||||||
@@ -2670,14 +2665,11 @@ async fn inactive_thread_file_change_approval_recovers_buffered_changes() {
|
|||||||
.expect("valid localized paths")
|
.expect("valid localized paths")
|
||||||
.expect("expected file change approval request");
|
.expect("expected file change approval request");
|
||||||
|
|
||||||
let ThreadInteractiveRequest::Approval(ApprovalRequest::ApplyPatch {
|
let ThreadInteractiveRequest::Approval(ApprovalRequest::ApplyPatch(approval)) = &request else {
|
||||||
changes, reason, ..
|
|
||||||
}) = &request
|
|
||||||
else {
|
|
||||||
panic!("expected apply-patch approval request");
|
panic!("expected apply-patch approval request");
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
changes,
|
&approval.changes,
|
||||||
&HashMap::from([(
|
&HashMap::from([(
|
||||||
PathBuf::from("README.md"),
|
PathBuf::from("README.md"),
|
||||||
FileChange::Add {
|
FileChange::Add {
|
||||||
@@ -2686,7 +2678,7 @@ async fn inactive_thread_file_change_approval_recovers_buffered_changes() {
|
|||||||
)])
|
)])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
reason,
|
&approval.reason,
|
||||||
&Some("command failed; retry without sandbox?".to_string())
|
&Some("command failed; retry without sandbox?".to_string())
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2728,11 +2720,7 @@ async fn inactive_thread_permissions_approval_preserves_file_system_permissions(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Permissions {
|
let Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Permissions(approval))) = app
|
||||||
environment_id,
|
|
||||||
permissions,
|
|
||||||
..
|
|
||||||
})) = app
|
|
||||||
.interactive_request_for_thread_request(thread_id, &request)
|
.interactive_request_for_thread_request(thread_id, &request)
|
||||||
.await
|
.await
|
||||||
.expect("valid localized paths")
|
.expect("valid localized paths")
|
||||||
@@ -2740,9 +2728,9 @@ async fn inactive_thread_permissions_approval_preserves_file_system_permissions(
|
|||||||
panic!("expected permissions approval request");
|
panic!("expected permissions approval request");
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(environment_id.as_deref(), Some("remote"));
|
assert_eq!(approval.environment_id.as_deref(), Some("remote"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
permissions,
|
approval.permissions,
|
||||||
RequestPermissionProfile {
|
RequestPermissionProfile {
|
||||||
network: Some(NetworkPermissions {
|
network: Some(NetworkPermissions {
|
||||||
enabled: Some(true),
|
enabled: Some(true),
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ impl App {
|
|||||||
let proposed_execpolicy_amendment = params.proposed_execpolicy_amendment.clone();
|
let proposed_execpolicy_amendment = params.proposed_execpolicy_amendment.clone();
|
||||||
let proposed_network_policy_amendments =
|
let proposed_network_policy_amendments =
|
||||||
params.proposed_network_policy_amendments.clone();
|
params.proposed_network_policy_amendments.clone();
|
||||||
Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Exec {
|
let approval = ExecApprovalRequest {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_label,
|
thread_label,
|
||||||
id: params
|
id: params
|
||||||
@@ -243,10 +243,14 @@ impl App {
|
|||||||
}),
|
}),
|
||||||
network_approval_context,
|
network_approval_context,
|
||||||
additional_permissions,
|
additional_permissions,
|
||||||
}))
|
};
|
||||||
|
Some(ThreadInteractiveRequest::Approval(ApprovalRequest::Exec(
|
||||||
|
approval,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
ServerRequest::FileChangeRequestApproval { params, .. } => Some(
|
ServerRequest::FileChangeRequestApproval { params, .. } => Some(
|
||||||
ThreadInteractiveRequest::Approval(ApprovalRequest::ApplyPatch {
|
ThreadInteractiveRequest::Approval(ApprovalRequest::ApplyPatch(
|
||||||
|
ApplyPatchApprovalRequest {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_label,
|
thread_label,
|
||||||
id: params.item_id.clone(),
|
id: params.item_id.clone(),
|
||||||
@@ -260,7 +264,8 @@ impl App {
|
|||||||
.await
|
.await
|
||||||
.map(crate::app_server_approval_conversions::file_update_changes_to_display)
|
.map(crate::app_server_approval_conversions::file_update_changes_to_display)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
}),
|
},
|
||||||
|
)),
|
||||||
),
|
),
|
||||||
ServerRequest::McpServerElicitationRequest { request_id, params } => {
|
ServerRequest::McpServerElicitationRequest { request_id, params } => {
|
||||||
if let Some(params) = AppLinkViewParams::from_url_app_server_request(
|
if let Some(params) = AppLinkViewParams::from_url_app_server_request(
|
||||||
@@ -284,13 +289,13 @@ impl App {
|
|||||||
message,
|
message,
|
||||||
..
|
..
|
||||||
} => Some(ThreadInteractiveRequest::Approval(
|
} => Some(ThreadInteractiveRequest::Approval(
|
||||||
ApprovalRequest::McpElicitation {
|
ApprovalRequest::McpElicitation(McpElicitationApprovalRequest {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_label,
|
thread_label,
|
||||||
server_name: params.server_name.clone(),
|
server_name: params.server_name.clone(),
|
||||||
request_id: request_id.clone(),
|
request_id: request_id.clone(),
|
||||||
message: message.clone(),
|
message: message.clone(),
|
||||||
},
|
}),
|
||||||
)),
|
)),
|
||||||
codex_app_server_protocol::McpServerElicitationRequest::OpenAiForm {
|
codex_app_server_protocol::McpServerElicitationRequest::OpenAiForm {
|
||||||
..
|
..
|
||||||
@@ -319,14 +324,14 @@ impl App {
|
|||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Some(ThreadInteractiveRequest::Approval(
|
Some(ThreadInteractiveRequest::Approval(
|
||||||
ApprovalRequest::Permissions {
|
ApprovalRequest::Permissions(PermissionsApprovalRequest {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_label,
|
thread_label,
|
||||||
call_id: params.item_id.clone(),
|
call_id: params.item_id.clone(),
|
||||||
environment_id: params.environment_id.clone(),
|
environment_id: params.environment_id.clone(),
|
||||||
reason: params.reason.clone(),
|
reason: params.reason.clone(),
|
||||||
permissions,
|
permissions,
|
||||||
},
|
}),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -350,20 +355,17 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_inactive_patch_preview(&mut self, request: &ApprovalRequest) {
|
fn render_inactive_patch_preview(&mut self, request: &ApprovalRequest) {
|
||||||
let ApprovalRequest::ApplyPatch {
|
let ApprovalRequest::ApplyPatch(request) = request else {
|
||||||
thread_label,
|
|
||||||
cwd,
|
|
||||||
changes,
|
|
||||||
..
|
|
||||||
} = request
|
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if thread_label.is_none() || changes.is_empty() {
|
if request.thread_label.is_none() || request.changes.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.chat_widget
|
self.chat_widget
|
||||||
.add_to_history(history_cell::new_patch_event(changes.clone(), cwd));
|
.add_to_history(history_cell::new_patch_event(
|
||||||
|
request.changes.clone(),
|
||||||
|
&request.cwd,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) async fn pending_inactive_thread_requests(&self) -> Vec<(ThreadId, ServerRequest)> {
|
pub(super) async fn pending_inactive_thread_requests(&self) -> Vec<(ThreadId, ServerRequest)> {
|
||||||
|
|||||||
@@ -71,86 +71,97 @@ use ratatui::widgets::Wrap;
|
|||||||
/// Request coming from the agent that needs user approval.
|
/// Request coming from the agent that needs user approval.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) enum ApprovalRequest {
|
pub(crate) enum ApprovalRequest {
|
||||||
Exec {
|
Exec(ExecApprovalRequest),
|
||||||
thread_id: ThreadId,
|
Permissions(PermissionsApprovalRequest),
|
||||||
thread_label: Option<String>,
|
ApplyPatch(ApplyPatchApprovalRequest),
|
||||||
id: String,
|
McpElicitation(McpElicitationApprovalRequest),
|
||||||
environment_id: Option<String>,
|
}
|
||||||
command: Vec<String>,
|
|
||||||
reason: Option<String>,
|
#[derive(Clone, Debug)]
|
||||||
available_decisions: Vec<CommandExecutionApprovalDecision>,
|
pub(crate) struct ExecApprovalRequest {
|
||||||
network_approval_context: Option<NetworkApprovalContext>,
|
pub thread_id: ThreadId,
|
||||||
additional_permissions: Option<AdditionalPermissionProfile>,
|
pub thread_label: Option<String>,
|
||||||
},
|
pub id: String,
|
||||||
Permissions {
|
pub environment_id: Option<String>,
|
||||||
thread_id: ThreadId,
|
pub command: Vec<String>,
|
||||||
thread_label: Option<String>,
|
pub reason: Option<String>,
|
||||||
call_id: String,
|
pub available_decisions: Vec<CommandExecutionApprovalDecision>,
|
||||||
environment_id: Option<String>,
|
pub network_approval_context: Option<NetworkApprovalContext>,
|
||||||
reason: Option<String>,
|
pub additional_permissions: Option<AdditionalPermissionProfile>,
|
||||||
permissions: RequestPermissionProfile,
|
}
|
||||||
},
|
|
||||||
ApplyPatch {
|
#[derive(Clone, Debug)]
|
||||||
thread_id: ThreadId,
|
pub(crate) struct PermissionsApprovalRequest {
|
||||||
thread_label: Option<String>,
|
pub thread_id: ThreadId,
|
||||||
id: String,
|
pub thread_label: Option<String>,
|
||||||
reason: Option<String>,
|
pub call_id: String,
|
||||||
cwd: AbsolutePathBuf,
|
pub environment_id: Option<String>,
|
||||||
changes: HashMap<PathBuf, FileChange>,
|
pub reason: Option<String>,
|
||||||
},
|
pub permissions: RequestPermissionProfile,
|
||||||
McpElicitation {
|
}
|
||||||
thread_id: ThreadId,
|
|
||||||
thread_label: Option<String>,
|
#[derive(Clone, Debug)]
|
||||||
server_name: String,
|
pub(crate) struct ApplyPatchApprovalRequest {
|
||||||
request_id: RequestId,
|
pub thread_id: ThreadId,
|
||||||
message: String,
|
pub thread_label: Option<String>,
|
||||||
},
|
pub id: String,
|
||||||
|
pub reason: Option<String>,
|
||||||
|
pub cwd: AbsolutePathBuf,
|
||||||
|
pub changes: HashMap<PathBuf, FileChange>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub(crate) struct McpElicitationApprovalRequest {
|
||||||
|
pub thread_id: ThreadId,
|
||||||
|
pub thread_label: Option<String>,
|
||||||
|
pub server_name: String,
|
||||||
|
pub request_id: RequestId,
|
||||||
|
pub message: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApprovalRequest {
|
impl ApprovalRequest {
|
||||||
fn thread_id(&self) -> ThreadId {
|
fn thread_id(&self) -> ThreadId {
|
||||||
match self {
|
match self {
|
||||||
ApprovalRequest::Exec { thread_id, .. }
|
ApprovalRequest::Exec(request) => request.thread_id,
|
||||||
| ApprovalRequest::Permissions { thread_id, .. }
|
ApprovalRequest::Permissions(request) => request.thread_id,
|
||||||
| ApprovalRequest::ApplyPatch { thread_id, .. }
|
ApprovalRequest::ApplyPatch(request) => request.thread_id,
|
||||||
| ApprovalRequest::McpElicitation { thread_id, .. } => *thread_id,
|
ApprovalRequest::McpElicitation(request) => request.thread_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thread_label(&self) -> Option<&str> {
|
fn thread_label(&self) -> Option<&str> {
|
||||||
match self {
|
match self {
|
||||||
ApprovalRequest::Exec { thread_label, .. }
|
ApprovalRequest::Exec(request) => request.thread_label.as_deref(),
|
||||||
| ApprovalRequest::Permissions { thread_label, .. }
|
ApprovalRequest::Permissions(request) => request.thread_label.as_deref(),
|
||||||
| ApprovalRequest::ApplyPatch { thread_label, .. }
|
ApprovalRequest::ApplyPatch(request) => request.thread_label.as_deref(),
|
||||||
| ApprovalRequest::McpElicitation { thread_label, .. } => thread_label.as_deref(),
|
ApprovalRequest::McpElicitation(request) => request.thread_label.as_deref(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn matches_resolved_request(&self, request: &ResolvedAppServerRequest) -> bool {
|
pub(super) fn matches_resolved_request(&self, request: &ResolvedAppServerRequest) -> bool {
|
||||||
match (self, request) {
|
match (self, request) {
|
||||||
(
|
(
|
||||||
ApprovalRequest::Exec { id, .. },
|
ApprovalRequest::Exec(request),
|
||||||
ResolvedAppServerRequest::ExecApproval { id: resolved_id },
|
ResolvedAppServerRequest::ExecApproval { id: resolved_id },
|
||||||
) => id == resolved_id,
|
) => request.id == *resolved_id,
|
||||||
(
|
(
|
||||||
ApprovalRequest::Permissions { call_id, .. },
|
ApprovalRequest::Permissions(request),
|
||||||
ResolvedAppServerRequest::PermissionsApproval { id },
|
ResolvedAppServerRequest::PermissionsApproval { id },
|
||||||
) => call_id == id,
|
) => request.call_id == *id,
|
||||||
(
|
(
|
||||||
ApprovalRequest::ApplyPatch { id, .. },
|
ApprovalRequest::ApplyPatch(request),
|
||||||
ResolvedAppServerRequest::FileChangeApproval { id: resolved_id },
|
ResolvedAppServerRequest::FileChangeApproval { id: resolved_id },
|
||||||
) => id == resolved_id,
|
) => request.id == *resolved_id,
|
||||||
(
|
(
|
||||||
ApprovalRequest::McpElicitation {
|
ApprovalRequest::McpElicitation(request),
|
||||||
server_name,
|
|
||||||
request_id,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
ResolvedAppServerRequest::McpElicitation {
|
ResolvedAppServerRequest::McpElicitation {
|
||||||
server_name: resolved_server_name,
|
server_name: resolved_server_name,
|
||||||
request_id: resolved_request_id,
|
request_id: resolved_request_id,
|
||||||
},
|
},
|
||||||
) => server_name == resolved_server_name && request_id == resolved_request_id,
|
) => {
|
||||||
|
request.server_name == *resolved_server_name
|
||||||
|
&& request.request_id == *resolved_request_id
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,19 +250,14 @@ impl ApprovalOverlay {
|
|||||||
list_keymap: &ListKeymap,
|
list_keymap: &ListKeymap,
|
||||||
) -> (Vec<ApprovalOption>, SelectionViewParams) {
|
) -> (Vec<ApprovalOption>, SelectionViewParams) {
|
||||||
let (options, title) = match request {
|
let (options, title) = match request {
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(request) => (
|
||||||
available_decisions,
|
|
||||||
network_approval_context,
|
|
||||||
additional_permissions,
|
|
||||||
..
|
|
||||||
} => (
|
|
||||||
exec_options(
|
exec_options(
|
||||||
available_decisions,
|
&request.available_decisions,
|
||||||
network_approval_context.as_ref(),
|
request.network_approval_context.as_ref(),
|
||||||
additional_permissions.as_ref(),
|
request.additional_permissions.as_ref(),
|
||||||
approval_keymap,
|
approval_keymap,
|
||||||
),
|
),
|
||||||
network_approval_context.as_ref().map_or_else(
|
request.network_approval_context.as_ref().map_or_else(
|
||||||
|| "Would you like to run the following command?".to_string(),
|
|| "Would you like to run the following command?".to_string(),
|
||||||
|network_approval_context| {
|
|network_approval_context| {
|
||||||
format!(
|
format!(
|
||||||
@@ -261,17 +267,17 @@ impl ApprovalOverlay {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ApprovalRequest::Permissions { .. } => (
|
ApprovalRequest::Permissions(_) => (
|
||||||
permissions_options(approval_keymap),
|
permissions_options(approval_keymap),
|
||||||
"Would you like to grant these permissions?".to_string(),
|
"Would you like to grant these permissions?".to_string(),
|
||||||
),
|
),
|
||||||
ApprovalRequest::ApplyPatch { .. } => (
|
ApprovalRequest::ApplyPatch(_) => (
|
||||||
patch_options(approval_keymap),
|
patch_options(approval_keymap),
|
||||||
"Would you like to make the following edits?".to_string(),
|
"Would you like to make the following edits?".to_string(),
|
||||||
),
|
),
|
||||||
ApprovalRequest::McpElicitation { server_name, .. } => (
|
ApprovalRequest::McpElicitation(request) => (
|
||||||
elicitation_options(approval_keymap),
|
elicitation_options(approval_keymap),
|
||||||
format!("{server_name} needs your approval."),
|
format!("{} needs your approval.", request.server_name),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -310,35 +316,31 @@ impl ApprovalOverlay {
|
|||||||
};
|
};
|
||||||
if let Some(request) = self.current_request.as_ref() {
|
if let Some(request) = self.current_request.as_ref() {
|
||||||
match (request, &option.decision) {
|
match (request, &option.decision) {
|
||||||
(
|
(ApprovalRequest::Exec(request), ApprovalDecision::Command(decision)) => {
|
||||||
ApprovalRequest::Exec { id, command, .. },
|
self.handle_exec_decision(&request.id, &request.command, decision.clone());
|
||||||
ApprovalDecision::Command(decision),
|
|
||||||
) => {
|
|
||||||
self.handle_exec_decision(id, command, decision.clone());
|
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
ApprovalRequest::Permissions {
|
ApprovalRequest::Permissions(request),
|
||||||
call_id,
|
|
||||||
permissions,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
ApprovalDecision::Permissions(decision),
|
ApprovalDecision::Permissions(decision),
|
||||||
) => self.handle_permissions_decision(call_id, permissions, *decision),
|
|
||||||
(
|
|
||||||
ApprovalRequest::ApplyPatch { id, .. },
|
|
||||||
ApprovalDecision::FileChange(decision),
|
|
||||||
) => {
|
) => {
|
||||||
self.handle_patch_decision(id, decision.clone());
|
self.handle_permissions_decision(
|
||||||
|
&request.call_id,
|
||||||
|
&request.permissions,
|
||||||
|
*decision,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
(ApprovalRequest::ApplyPatch(request), ApprovalDecision::FileChange(decision)) => {
|
||||||
|
self.handle_patch_decision(&request.id, decision.clone());
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
ApprovalRequest::McpElicitation {
|
ApprovalRequest::McpElicitation(request),
|
||||||
server_name,
|
|
||||||
request_id,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
ApprovalDecision::McpElicitation(decision),
|
ApprovalDecision::McpElicitation(decision),
|
||||||
) => {
|
) => {
|
||||||
self.handle_elicitation_decision(server_name, request_id, *decision);
|
self.handle_elicitation_decision(
|
||||||
|
&request.server_name,
|
||||||
|
&request.request_id,
|
||||||
|
*decision,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -358,22 +360,22 @@ impl ApprovalOverlay {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if request.thread_label().is_none() {
|
if request.thread_label().is_none() {
|
||||||
let subject = match request {
|
let network_approval_context = match request {
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(request) => request.network_approval_context.as_ref(),
|
||||||
network_approval_context: Some(network_approval_context),
|
ApprovalRequest::Permissions(_)
|
||||||
..
|
| ApprovalRequest::ApplyPatch(_)
|
||||||
} => history_cell::ApprovalDecisionSubject::NetworkAccess {
|
| ApprovalRequest::McpElicitation(_) => None,
|
||||||
|
};
|
||||||
|
let subject = if let Some(network_approval_context) = network_approval_context {
|
||||||
|
history_cell::ApprovalDecisionSubject::NetworkAccess {
|
||||||
target: network_approval_target(network_approval_context, command),
|
target: network_approval_target(network_approval_context, command),
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
if let Some(target) = network_approval_command_target(command) {
|
|
||||||
history_cell::ApprovalDecisionSubject::NetworkAccess {
|
|
||||||
target: target.to_string(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
history_cell::ApprovalDecisionSubject::Command(command.to_vec())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else if let Some(target) = network_approval_command_target(command) {
|
||||||
|
history_cell::ApprovalDecisionSubject::NetworkAccess {
|
||||||
|
target: target.to_string(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
history_cell::ApprovalDecisionSubject::Command(command.to_vec())
|
||||||
};
|
};
|
||||||
let cell = history_cell::new_approval_decision_cell(
|
let cell = history_cell::new_approval_decision_cell(
|
||||||
subject,
|
subject,
|
||||||
@@ -488,35 +490,27 @@ impl ApprovalOverlay {
|
|||||||
&& let Some(request) = self.current_request.as_ref()
|
&& let Some(request) = self.current_request.as_ref()
|
||||||
{
|
{
|
||||||
match request {
|
match request {
|
||||||
ApprovalRequest::Exec { id, command, .. } => {
|
ApprovalRequest::Exec(request) => {
|
||||||
self.handle_exec_decision(
|
self.handle_exec_decision(
|
||||||
id,
|
&request.id,
|
||||||
command,
|
&request.command,
|
||||||
CommandExecutionApprovalDecision::Cancel,
|
CommandExecutionApprovalDecision::Cancel,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ApprovalRequest::Permissions {
|
ApprovalRequest::Permissions(request) => {
|
||||||
call_id,
|
|
||||||
permissions,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
self.handle_permissions_decision(
|
self.handle_permissions_decision(
|
||||||
call_id,
|
&request.call_id,
|
||||||
permissions,
|
&request.permissions,
|
||||||
PermissionsDecision::Deny,
|
PermissionsDecision::Deny,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ApprovalRequest::ApplyPatch { id, .. } => {
|
ApprovalRequest::ApplyPatch(request) => {
|
||||||
self.handle_patch_decision(id, FileChangeApprovalDecision::Cancel);
|
self.handle_patch_decision(&request.id, FileChangeApprovalDecision::Cancel);
|
||||||
}
|
}
|
||||||
ApprovalRequest::McpElicitation {
|
ApprovalRequest::McpElicitation(request) => {
|
||||||
server_name,
|
|
||||||
request_id,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
self.handle_elicitation_decision(
|
self.handle_elicitation_decision(
|
||||||
server_name,
|
&request.server_name,
|
||||||
request_id,
|
&request.request_id,
|
||||||
McpServerElicitationAction::Cancel,
|
McpServerElicitationAction::Cancel,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -675,35 +669,27 @@ fn network_approval_command_target(command: &[String]) -> Option<&str> {
|
|||||||
|
|
||||||
fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
||||||
match request {
|
match request {
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(request) => {
|
||||||
thread_label,
|
|
||||||
environment_id,
|
|
||||||
reason,
|
|
||||||
command,
|
|
||||||
network_approval_context,
|
|
||||||
additional_permissions,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut header: Vec<Line<'static>> = Vec::new();
|
let mut header: Vec<Line<'static>> = Vec::new();
|
||||||
if let Some(thread_label) = thread_label {
|
if let Some(thread_label) = &request.thread_label {
|
||||||
header.push(Line::from(vec![
|
header.push(Line::from(vec![
|
||||||
"Thread: ".into(),
|
"Thread: ".into(),
|
||||||
thread_label.clone().bold(),
|
thread_label.clone().bold(),
|
||||||
]));
|
]));
|
||||||
header.push(Line::from(""));
|
header.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(environment_id) = environment_id {
|
if let Some(environment_id) = &request.environment_id {
|
||||||
header.push(Line::from(vec![
|
header.push(Line::from(vec![
|
||||||
"Environment: ".into(),
|
"Environment: ".into(),
|
||||||
environment_id.clone().bold(),
|
environment_id.clone().bold(),
|
||||||
]));
|
]));
|
||||||
header.push(Line::from(""));
|
header.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(reason) = reason {
|
if let Some(reason) = &request.reason {
|
||||||
header.push(Line::from(vec!["Reason: ".into(), reason.clone().italic()]));
|
header.push(Line::from(vec!["Reason: ".into(), reason.clone().italic()]));
|
||||||
header.push(Line::from(""));
|
header.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(additional_permissions) = additional_permissions
|
if let Some(additional_permissions) = &request.additional_permissions
|
||||||
&& let Some(rule_line) = format_additional_permissions_rule(additional_permissions)
|
&& let Some(rule_line) = format_additional_permissions_rule(additional_permissions)
|
||||||
{
|
{
|
||||||
header.push(Line::from(vec![
|
header.push(Line::from(vec![
|
||||||
@@ -712,43 +698,37 @@ fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
|||||||
]));
|
]));
|
||||||
header.push(Line::from(""));
|
header.push(Line::from(""));
|
||||||
}
|
}
|
||||||
let full_cmd = strip_bash_lc_and_escape(command);
|
let full_cmd = strip_bash_lc_and_escape(&request.command);
|
||||||
let mut full_cmd_lines = highlight_bash_to_lines(&full_cmd);
|
let mut full_cmd_lines = highlight_bash_to_lines(&full_cmd);
|
||||||
if let Some(first) = full_cmd_lines.first_mut() {
|
if let Some(first) = full_cmd_lines.first_mut() {
|
||||||
first.spans.insert(0, Span::from("$ "));
|
first.spans.insert(0, Span::from("$ "));
|
||||||
}
|
}
|
||||||
if network_approval_context.is_none() {
|
if request.network_approval_context.is_none() {
|
||||||
header.extend(full_cmd_lines);
|
header.extend(full_cmd_lines);
|
||||||
}
|
}
|
||||||
Box::new(Paragraph::new(header).wrap(Wrap { trim: false }))
|
Box::new(Paragraph::new(header).wrap(Wrap { trim: false }))
|
||||||
}
|
}
|
||||||
ApprovalRequest::Permissions {
|
ApprovalRequest::Permissions(request) => {
|
||||||
thread_label,
|
|
||||||
environment_id,
|
|
||||||
reason,
|
|
||||||
permissions,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut header: Vec<Line<'static>> = Vec::new();
|
let mut header: Vec<Line<'static>> = Vec::new();
|
||||||
if let Some(thread_label) = thread_label {
|
if let Some(thread_label) = &request.thread_label {
|
||||||
header.push(Line::from(vec![
|
header.push(Line::from(vec![
|
||||||
"Thread: ".into(),
|
"Thread: ".into(),
|
||||||
thread_label.clone().bold(),
|
thread_label.clone().bold(),
|
||||||
]));
|
]));
|
||||||
header.push(Line::from(""));
|
header.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(environment_id) = environment_id {
|
if let Some(environment_id) = &request.environment_id {
|
||||||
header.push(Line::from(vec![
|
header.push(Line::from(vec![
|
||||||
"Environment: ".into(),
|
"Environment: ".into(),
|
||||||
environment_id.clone().bold(),
|
environment_id.clone().bold(),
|
||||||
]));
|
]));
|
||||||
header.push(Line::from(""));
|
header.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(reason) = reason {
|
if let Some(reason) = &request.reason {
|
||||||
header.push(Line::from(vec!["Reason: ".into(), reason.clone().italic()]));
|
header.push(Line::from(vec!["Reason: ".into(), reason.clone().italic()]));
|
||||||
header.push(Line::from(""));
|
header.push(Line::from(""));
|
||||||
}
|
}
|
||||||
if let Some(rule_line) = format_requested_permissions_rule(permissions) {
|
if let Some(rule_line) = format_requested_permissions_rule(&request.permissions) {
|
||||||
header.push(Line::from(vec![
|
header.push(Line::from(vec![
|
||||||
"Permission rule: ".into(),
|
"Permission rule: ".into(),
|
||||||
rule_line.cyan(),
|
rule_line.cyan(),
|
||||||
@@ -756,19 +736,15 @@ fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
|||||||
}
|
}
|
||||||
Box::new(Paragraph::new(header).wrap(Wrap { trim: false }))
|
Box::new(Paragraph::new(header).wrap(Wrap { trim: false }))
|
||||||
}
|
}
|
||||||
ApprovalRequest::ApplyPatch {
|
ApprovalRequest::ApplyPatch(request) => {
|
||||||
thread_label,
|
|
||||||
reason,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut header: Vec<Box<dyn Renderable>> = Vec::new();
|
let mut header: Vec<Box<dyn Renderable>> = Vec::new();
|
||||||
if let Some(thread_label) = thread_label {
|
if let Some(thread_label) = &request.thread_label {
|
||||||
header.push(Box::new(Line::from(vec![
|
header.push(Box::new(Line::from(vec![
|
||||||
"Thread: ".into(),
|
"Thread: ".into(),
|
||||||
thread_label.clone().bold(),
|
thread_label.clone().bold(),
|
||||||
])));
|
])));
|
||||||
}
|
}
|
||||||
if let Some(reason) = reason
|
if let Some(reason) = &request.reason
|
||||||
&& !reason.is_empty()
|
&& !reason.is_empty()
|
||||||
{
|
{
|
||||||
if !header.is_empty() {
|
if !header.is_empty() {
|
||||||
@@ -784,14 +760,9 @@ fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
|||||||
}
|
}
|
||||||
Box::new(ColumnRenderable::with(header))
|
Box::new(ColumnRenderable::with(header))
|
||||||
}
|
}
|
||||||
ApprovalRequest::McpElicitation {
|
ApprovalRequest::McpElicitation(request) => {
|
||||||
thread_label,
|
|
||||||
server_name,
|
|
||||||
message,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
if let Some(thread_label) = thread_label {
|
if let Some(thread_label) = &request.thread_label {
|
||||||
lines.push(Line::from(vec![
|
lines.push(Line::from(vec![
|
||||||
"Thread: ".into(),
|
"Thread: ".into(),
|
||||||
thread_label.clone().bold(),
|
thread_label.clone().bold(),
|
||||||
@@ -799,9 +770,9 @@ fn build_header(request: &ApprovalRequest) -> Box<dyn Renderable> {
|
|||||||
lines.push(Line::from(""));
|
lines.push(Line::from(""));
|
||||||
}
|
}
|
||||||
lines.extend([
|
lines.extend([
|
||||||
Line::from(vec!["Server: ".into(), server_name.clone().bold()]),
|
Line::from(vec!["Server: ".into(), request.server_name.clone().bold()]),
|
||||||
Line::from(""),
|
Line::from(""),
|
||||||
Line::from(message.clone()),
|
Line::from(request.message.clone()),
|
||||||
]);
|
]);
|
||||||
let header = Paragraph::new(lines).wrap(Wrap { trim: false });
|
let header = Paragraph::new(lines).wrap(Wrap { trim: false });
|
||||||
Box::new(header)
|
Box::new(header)
|
||||||
@@ -1226,7 +1197,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn make_exec_request() -> ApprovalRequest {
|
fn make_exec_request() -> ApprovalRequest {
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1239,11 +1210,11 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_permissions_request() -> ApprovalRequest {
|
fn make_permissions_request() -> ApprovalRequest {
|
||||||
ApprovalRequest::Permissions {
|
ApprovalRequest::Permissions(PermissionsApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
call_id: "test".to_string(),
|
call_id: "test".to_string(),
|
||||||
@@ -1258,17 +1229,17 @@ mod tests {
|
|||||||
Some(vec![absolute_path("/tmp/out.txt")]),
|
Some(vec![absolute_path("/tmp/out.txt")]),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_elicitation_request() -> ApprovalRequest {
|
fn make_elicitation_request() -> ApprovalRequest {
|
||||||
ApprovalRequest::McpElicitation {
|
ApprovalRequest::McpElicitation(McpElicitationApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
server_name: "test-server".to_string(),
|
server_name: "test-server".to_string(),
|
||||||
request_id: RequestId::String("request-1".to_string()),
|
request_id: RequestId::String("request-1".to_string()),
|
||||||
message: "Need more information".to_string(),
|
message: "Need more information".to_string(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1367,7 +1338,7 @@ mod tests {
|
|||||||
let (tx, mut rx) = unbounded_channel::<AppEvent>();
|
let (tx, mut rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let mut view = make_overlay(
|
let mut view = make_overlay(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1380,7 +1351,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
);
|
);
|
||||||
@@ -1411,7 +1382,7 @@ mod tests {
|
|||||||
action: NetworkPolicyRuleAction::Deny,
|
action: NetworkPolicyRuleAction::Deny,
|
||||||
};
|
};
|
||||||
let mut view = make_overlay(
|
let mut view = make_overlay(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1429,7 +1400,7 @@ mod tests {
|
|||||||
protocol: NetworkApprovalProtocol::Https,
|
protocol: NetworkApprovalProtocol::Https,
|
||||||
}),
|
}),
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
);
|
);
|
||||||
@@ -1486,7 +1457,7 @@ mod tests {
|
|||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let thread_id = ThreadId::new();
|
let thread_id = ThreadId::new();
|
||||||
let mut view = make_overlay(
|
let mut view = make_overlay(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_label: Some("Robie [explorer]".to_string()),
|
thread_label: Some("Robie [explorer]".to_string()),
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1499,7 +1470,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
);
|
);
|
||||||
@@ -1521,7 +1492,7 @@ mod tests {
|
|||||||
let mut keymap = crate::keymap::RuntimeKeymap::defaults();
|
let mut keymap = crate::keymap::RuntimeKeymap::defaults();
|
||||||
keymap.approval.open_thread = vec![key_hint::plain(KeyCode::Char('x'))];
|
keymap.approval.open_thread = vec![key_hint::plain(KeyCode::Char('x'))];
|
||||||
let mut view = make_overlay_with_keymap(
|
let mut view = make_overlay_with_keymap(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_label: Some("Robie [explorer]".to_string()),
|
thread_label: Some("Robie [explorer]".to_string()),
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1534,7 +1505,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
keymap.approval,
|
keymap.approval,
|
||||||
@@ -1560,7 +1531,7 @@ mod tests {
|
|||||||
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let view = make_overlay(
|
let view = make_overlay(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: Some("Robie [explorer]".to_string()),
|
thread_label: Some("Robie [explorer]".to_string()),
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1573,7 +1544,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
);
|
);
|
||||||
@@ -1589,7 +1560,7 @@ mod tests {
|
|||||||
let (tx, mut rx) = unbounded_channel::<AppEvent>();
|
let (tx, mut rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let mut view = make_overlay(
|
let mut view = make_overlay(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1607,7 +1578,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
);
|
);
|
||||||
@@ -1642,7 +1613,7 @@ mod tests {
|
|||||||
let (tx, mut rx) = unbounded_channel::<AppEvent>();
|
let (tx, mut rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let mut view = make_overlay(
|
let mut view = make_overlay(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
@@ -1665,7 +1636,7 @@ mod tests {
|
|||||||
protocol: NetworkApprovalProtocol::Https,
|
protocol: NetworkApprovalProtocol::Https,
|
||||||
}),
|
}),
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
);
|
);
|
||||||
@@ -1682,7 +1653,7 @@ mod tests {
|
|||||||
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let command = vec!["echo".into(), "hello".into(), "world".into()];
|
let command = vec!["echo".into(), "hello".into(), "world".into()];
|
||||||
let exec_request = ApprovalRequest::Exec {
|
let exec_request = ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".into(),
|
id: "test".into(),
|
||||||
@@ -1695,7 +1666,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
};
|
});
|
||||||
|
|
||||||
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 80, view.desired_height(/*width*/ 80)));
|
let mut buf = Buffer::empty(Rect::new(0, 0, 80, view.desired_height(/*width*/ 80)));
|
||||||
@@ -1983,7 +1954,7 @@ mod tests {
|
|||||||
fn additional_permissions_prompt_shows_permission_rule_line() {
|
fn additional_permissions_prompt_shows_permission_rule_line() {
|
||||||
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let exec_request = ApprovalRequest::Exec {
|
let exec_request = ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".into(),
|
id: "test".into(),
|
||||||
@@ -2007,7 +1978,7 @@ mod tests {
|
|||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
};
|
});
|
||||||
|
|
||||||
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 100, view.desired_height(/*width*/ 100)));
|
let mut buf = Buffer::empty(Rect::new(0, 0, 100, view.desired_height(/*width*/ 100)));
|
||||||
@@ -2040,7 +2011,7 @@ mod tests {
|
|||||||
fn additional_permissions_prompt_snapshot() {
|
fn additional_permissions_prompt_snapshot() {
|
||||||
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let exec_request = ApprovalRequest::Exec {
|
let exec_request = ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".into(),
|
id: "test".into(),
|
||||||
@@ -2064,7 +2035,7 @@ mod tests {
|
|||||||
.into(),
|
.into(),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
};
|
});
|
||||||
|
|
||||||
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
||||||
assert_snapshot!(
|
assert_snapshot!(
|
||||||
@@ -2095,14 +2066,14 @@ mod tests {
|
|||||||
content: "one\ntwo\nthree\n".to_string(),
|
content: "one\ntwo\nthree\n".to_string(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let request = ApprovalRequest::ApplyPatch {
|
let request = ApprovalRequest::ApplyPatch(ApplyPatchApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: Some("Banach [worker]".to_string()),
|
thread_label: Some("Banach [worker]".to_string()),
|
||||||
id: "test".to_string(),
|
id: "test".to_string(),
|
||||||
reason: None,
|
reason: None,
|
||||||
cwd: absolute_path("/tmp"),
|
cwd: absolute_path("/tmp"),
|
||||||
changes,
|
changes,
|
||||||
};
|
});
|
||||||
let keymap = crate::keymap::RuntimeKeymap::defaults();
|
let keymap = crate::keymap::RuntimeKeymap::defaults();
|
||||||
let view = ApprovalOverlay::new(
|
let view = ApprovalOverlay::new(
|
||||||
request,
|
request,
|
||||||
@@ -2121,7 +2092,7 @@ mod tests {
|
|||||||
fn network_exec_prompt_title_includes_host() {
|
fn network_exec_prompt_title_includes_host() {
|
||||||
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx);
|
let tx = AppEventSender::new(tx);
|
||||||
let exec_request = ApprovalRequest::Exec {
|
let exec_request = ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".into(),
|
id: "test".into(),
|
||||||
@@ -2144,7 +2115,7 @@ mod tests {
|
|||||||
protocol: NetworkApprovalProtocol::Https,
|
protocol: NetworkApprovalProtocol::Https,
|
||||||
}),
|
}),
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
};
|
});
|
||||||
|
|
||||||
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
let view = make_overlay(exec_request, tx, Features::with_defaults());
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 100, view.desired_height(/*width*/ 100)));
|
let mut buf = Buffer::empty(Rect::new(0, 0, 100, view.desired_height(/*width*/ 100)));
|
||||||
@@ -2258,7 +2229,7 @@ mod tests {
|
|||||||
let (tx_raw, mut rx) = unbounded_channel::<AppEvent>();
|
let (tx_raw, mut rx) = unbounded_channel::<AppEvent>();
|
||||||
let tx = AppEventSender::new(tx_raw);
|
let tx = AppEventSender::new(tx_raw);
|
||||||
let mut view = make_overlay(
|
let mut view = make_overlay(
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: ThreadId::new(),
|
thread_id: ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "test".into(),
|
id: "test".into(),
|
||||||
@@ -2274,7 +2245,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
},
|
}),
|
||||||
tx,
|
tx,
|
||||||
Features::with_defaults(),
|
Features::with_defaults(),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -66,8 +66,12 @@ pub(crate) use app_link_view::AppLinkElicitationTarget;
|
|||||||
pub(crate) use app_link_view::AppLinkSuggestionType;
|
pub(crate) use app_link_view::AppLinkSuggestionType;
|
||||||
pub(crate) use app_link_view::AppLinkView;
|
pub(crate) use app_link_view::AppLinkView;
|
||||||
pub(crate) use app_link_view::AppLinkViewParams;
|
pub(crate) use app_link_view::AppLinkViewParams;
|
||||||
|
pub(crate) use approval_overlay::ApplyPatchApprovalRequest;
|
||||||
pub(crate) use approval_overlay::ApprovalOverlay;
|
pub(crate) use approval_overlay::ApprovalOverlay;
|
||||||
pub(crate) use approval_overlay::ApprovalRequest;
|
pub(crate) use approval_overlay::ApprovalRequest;
|
||||||
|
pub(crate) use approval_overlay::ExecApprovalRequest;
|
||||||
|
pub(crate) use approval_overlay::McpElicitationApprovalRequest;
|
||||||
|
pub(crate) use approval_overlay::PermissionsApprovalRequest;
|
||||||
pub(crate) use approval_overlay::format_requested_permissions_rule;
|
pub(crate) use approval_overlay::format_requested_permissions_rule;
|
||||||
pub(crate) use mcp_server_elicitation::McpServerElicitationFormRequest;
|
pub(crate) use mcp_server_elicitation::McpServerElicitationFormRequest;
|
||||||
pub(crate) use mcp_server_elicitation::McpServerElicitationOverlay;
|
pub(crate) use mcp_server_elicitation::McpServerElicitationOverlay;
|
||||||
@@ -1906,7 +1910,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn exec_request() -> ApprovalRequest {
|
fn exec_request() -> ApprovalRequest {
|
||||||
ApprovalRequest::Exec {
|
ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: codex_protocol::ThreadId::new(),
|
thread_id: codex_protocol::ThreadId::new(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: "1".to_string(),
|
id: "1".to_string(),
|
||||||
@@ -1919,7 +1923,7 @@ mod tests {
|
|||||||
],
|
],
|
||||||
network_approval_context: None,
|
network_approval_context: None,
|
||||||
additional_permissions: None,
|
additional_permissions: None,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|||||||
@@ -263,6 +263,7 @@ use crate::app_event::WindowsSandboxEnableMode;
|
|||||||
use crate::app_event_sender::AppEventSender;
|
use crate::app_event_sender::AppEventSender;
|
||||||
use crate::auto_review_denials;
|
use crate::auto_review_denials;
|
||||||
use crate::auto_review_denials::RecentAutoReviewDenials;
|
use crate::auto_review_denials::RecentAutoReviewDenials;
|
||||||
|
use crate::bottom_pane::ApplyPatchApprovalRequest;
|
||||||
use crate::bottom_pane::ApprovalRequest;
|
use crate::bottom_pane::ApprovalRequest;
|
||||||
use crate::bottom_pane::BottomPane;
|
use crate::bottom_pane::BottomPane;
|
||||||
use crate::bottom_pane::BottomPaneParams;
|
use crate::bottom_pane::BottomPaneParams;
|
||||||
@@ -270,15 +271,18 @@ use crate::bottom_pane::CancellationEvent;
|
|||||||
use crate::bottom_pane::CollaborationModeIndicator;
|
use crate::bottom_pane::CollaborationModeIndicator;
|
||||||
use crate::bottom_pane::ColumnWidthMode;
|
use crate::bottom_pane::ColumnWidthMode;
|
||||||
use crate::bottom_pane::DOUBLE_PRESS_QUIT_SHORTCUT_ENABLED;
|
use crate::bottom_pane::DOUBLE_PRESS_QUIT_SHORTCUT_ENABLED;
|
||||||
|
use crate::bottom_pane::ExecApprovalRequest;
|
||||||
use crate::bottom_pane::ExperimentalFeatureItem;
|
use crate::bottom_pane::ExperimentalFeatureItem;
|
||||||
use crate::bottom_pane::ExperimentalFeaturesView;
|
use crate::bottom_pane::ExperimentalFeaturesView;
|
||||||
use crate::bottom_pane::GoalStatusIndicator;
|
use crate::bottom_pane::GoalStatusIndicator;
|
||||||
use crate::bottom_pane::HistoryEntry;
|
use crate::bottom_pane::HistoryEntry;
|
||||||
use crate::bottom_pane::InputResult;
|
use crate::bottom_pane::InputResult;
|
||||||
use crate::bottom_pane::LocalImageAttachment;
|
use crate::bottom_pane::LocalImageAttachment;
|
||||||
|
use crate::bottom_pane::McpElicitationApprovalRequest;
|
||||||
use crate::bottom_pane::McpServerElicitationFormRequest;
|
use crate::bottom_pane::McpServerElicitationFormRequest;
|
||||||
use crate::bottom_pane::MemoriesSettingsView;
|
use crate::bottom_pane::MemoriesSettingsView;
|
||||||
use crate::bottom_pane::MentionBinding;
|
use crate::bottom_pane::MentionBinding;
|
||||||
|
use crate::bottom_pane::PermissionsApprovalRequest;
|
||||||
use crate::bottom_pane::QUIT_SHORTCUT_TIMEOUT;
|
use crate::bottom_pane::QUIT_SHORTCUT_TIMEOUT;
|
||||||
use crate::bottom_pane::QueuedInputAction;
|
use crate::bottom_pane::QueuedInputAction;
|
||||||
use crate::bottom_pane::SelectionAction;
|
use crate::bottom_pane::SelectionAction;
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ impl ChatWidget {
|
|||||||
self.notify(Notification::ExecApprovalRequested { command });
|
self.notify(Notification::ExecApprovalRequested { command });
|
||||||
|
|
||||||
let available_decisions = ev.effective_available_decisions();
|
let available_decisions = ev.effective_available_decisions();
|
||||||
let request = ApprovalRequest::Exec {
|
let request = ApprovalRequest::Exec(ExecApprovalRequest {
|
||||||
thread_id: self.thread_id.unwrap_or_default(),
|
thread_id: self.thread_id.unwrap_or_default(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: ev.effective_approval_id(),
|
id: ev.effective_approval_id(),
|
||||||
@@ -297,7 +297,7 @@ impl ChatWidget {
|
|||||||
available_decisions,
|
available_decisions,
|
||||||
network_approval_context: ev.network_approval_context,
|
network_approval_context: ev.network_approval_context,
|
||||||
additional_permissions: ev.additional_permissions,
|
additional_permissions: ev.additional_permissions,
|
||||||
};
|
});
|
||||||
self.bottom_pane
|
self.bottom_pane
|
||||||
.push_approval_request(request, &self.config.features);
|
.push_approval_request(request, &self.config.features);
|
||||||
self.set_ambient_pet_notification(
|
self.set_ambient_pet_notification(
|
||||||
@@ -310,14 +310,14 @@ impl ChatWidget {
|
|||||||
pub(crate) fn handle_apply_patch_approval_now(&mut self, ev: ApplyPatchApprovalRequestEvent) {
|
pub(crate) fn handle_apply_patch_approval_now(&mut self, ev: ApplyPatchApprovalRequestEvent) {
|
||||||
self.flush_answer_stream_with_separator();
|
self.flush_answer_stream_with_separator();
|
||||||
|
|
||||||
let request = ApprovalRequest::ApplyPatch {
|
let request = ApprovalRequest::ApplyPatch(ApplyPatchApprovalRequest {
|
||||||
thread_id: self.thread_id.unwrap_or_default(),
|
thread_id: self.thread_id.unwrap_or_default(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
id: ev.call_id,
|
id: ev.call_id,
|
||||||
reason: ev.reason,
|
reason: ev.reason,
|
||||||
changes: ev.changes.clone(),
|
changes: ev.changes.clone(),
|
||||||
cwd: self.config.cwd.clone(),
|
cwd: self.config.cwd.clone(),
|
||||||
};
|
});
|
||||||
self.bottom_pane
|
self.bottom_pane
|
||||||
.push_approval_request(request, &self.config.features);
|
.push_approval_request(request, &self.config.features);
|
||||||
self.set_ambient_pet_notification(
|
self.set_ambient_pet_notification(
|
||||||
@@ -361,13 +361,13 @@ impl ChatWidget {
|
|||||||
} else {
|
} else {
|
||||||
match params.request {
|
match params.request {
|
||||||
McpServerElicitationRequest::Form { message, .. } => {
|
McpServerElicitationRequest::Form { message, .. } => {
|
||||||
let request = ApprovalRequest::McpElicitation {
|
let request = ApprovalRequest::McpElicitation(McpElicitationApprovalRequest {
|
||||||
thread_id,
|
thread_id,
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
server_name: params.server_name,
|
server_name: params.server_name,
|
||||||
request_id,
|
request_id,
|
||||||
message,
|
message,
|
||||||
};
|
});
|
||||||
self.bottom_pane
|
self.bottom_pane
|
||||||
.push_approval_request(request, &self.config.features);
|
.push_approval_request(request, &self.config.features);
|
||||||
}
|
}
|
||||||
@@ -434,14 +434,14 @@ impl ChatWidget {
|
|||||||
|
|
||||||
pub(crate) fn handle_request_permissions_now(&mut self, ev: RequestPermissionsEvent) {
|
pub(crate) fn handle_request_permissions_now(&mut self, ev: RequestPermissionsEvent) {
|
||||||
self.flush_answer_stream_with_separator();
|
self.flush_answer_stream_with_separator();
|
||||||
let request = ApprovalRequest::Permissions {
|
let request = ApprovalRequest::Permissions(PermissionsApprovalRequest {
|
||||||
thread_id: self.thread_id.unwrap_or_default(),
|
thread_id: self.thread_id.unwrap_or_default(),
|
||||||
thread_label: None,
|
thread_label: None,
|
||||||
call_id: ev.call_id,
|
call_id: ev.call_id,
|
||||||
environment_id: ev.environment_id,
|
environment_id: ev.environment_id,
|
||||||
reason: ev.reason,
|
reason: ev.reason,
|
||||||
permissions: ev.permissions,
|
permissions: ev.permissions,
|
||||||
};
|
});
|
||||||
self.bottom_pane
|
self.bottom_pane
|
||||||
.push_approval_request(request, &self.config.features);
|
.push_approval_request(request, &self.config.features);
|
||||||
self.set_ambient_pet_notification(
|
self.set_ambient_pet_notification(
|
||||||
|
|||||||
Reference in new issue
Block a user