Harden local tool execution

This commit is contained in:
Georg Bauer
2026-07-26 14:36:38 +02:00
parent 171b041ba6
commit c9f0c3661c
7 changed files with 1018 additions and 141 deletions

View File

@@ -103,6 +103,11 @@ pub(crate) struct App {
#[cfg(target_os = "macos")]
active_tools: Option<crate::agent::ActiveTools>,
#[cfg(target_os = "macos")]
pub(super) tool_cards: Vec<crate::agent::ToolCard>,
#[cfg(target_os = "macos")]
pub(super) pending_tool_approval:
Option<(crate::agent::ApprovalPrompt, std::sync::mpsc::Sender<bool>)>,
#[cfg(target_os = "macos")]
active_titling: Option<generation::TitleRequest>,
#[cfg(target_os = "macos")]
runtime_config: Arc<RwLock<Config>>,
@@ -199,6 +204,10 @@ pub(crate) enum Message {
ComposerChanged(String),
ToggleReasoning(usize),
OpenLink(markdown::Url),
CopyToolText(String),
OpenToolOutput(PathBuf),
AllowToolOnce,
DenyTool,
SubmitPrompt,
StopGeneration,
GenerationTick,
@@ -316,6 +325,10 @@ impl App {
#[cfg(target_os = "macos")]
active_tools: None,
#[cfg(target_os = "macos")]
tool_cards: Vec::new(),
#[cfg(target_os = "macos")]
pending_tool_approval: None,
#[cfg(target_os = "macos")]
active_titling: None,
#[cfg(target_os = "macos")]
runtime_config,
@@ -415,6 +428,10 @@ impl App {
#[cfg(target_os = "macos")]
active_tools: None,
#[cfg(target_os = "macos")]
tool_cards: Vec::new(),
#[cfg(target_os = "macos")]
pending_tool_approval: None,
#[cfg(target_os = "macos")]
active_titling: None,
#[cfg(target_os = "macos")]
runtime_config,
@@ -778,6 +795,25 @@ impl App {
self.error = Some(format!("Could not open the link: {error}"));
}
}
Message::CopyToolText(value) => return iced::clipboard::write(value),
Message::OpenToolOutput(path) => {
if let Err(error) = std::process::Command::new("open").arg(path).spawn() {
self.error = Some(format!("Could not open the tool output: {error}"));
}
}
Message::AllowToolOnce => {
#[cfg(target_os = "macos")]
if let Some((_, decision)) = self.pending_tool_approval.take() {
let _ = decision.send(true);
}
}
Message::DenyTool =>
{
#[cfg(target_os = "macos")]
if let Some((_, decision)) = self.pending_tool_approval.take() {
let _ = decision.send(false);
}
}
Message::SubmitPrompt => {
self.start_generation();
return scroll_chat_to_end();
@@ -794,6 +830,12 @@ impl App {
active.cancel.store(true, Ordering::Relaxed);
}
#[cfg(target_os = "macos")]
if let Some((_, decision)) = self.pending_tool_approval.take() {
let _ = decision.send(false);
}
#[cfg(target_os = "macos")]
self.stop_agent_jobs();
#[cfg(target_os = "macos")]
if let Some(compaction) = &self.active_compaction {
compaction.active.cancel.store(true, Ordering::Relaxed);
}
@@ -1019,6 +1061,10 @@ impl App {
if self.selected_session == Some(session_id) {
return Task::none();
}
#[cfg(target_os = "macos")]
self.stop_agent_jobs();
#[cfg(target_os = "macos")]
self.tool_cards.clear();
let saved_context = self
.projects
.iter()
@@ -1298,6 +1344,10 @@ impl Drop for App {
if let Some(active) = &self.active_tools {
active.cancel.store(true, Ordering::Relaxed);
}
#[cfg(target_os = "macos")]
if let Some((_, decision)) = self.pending_tool_approval.take() {
let _ = decision.send(false);
}
}
}