steer_tui/tui/handlers/
approval.rs1use crate::error::Error;
2use crate::error::Result;
3use crate::tui::Tui;
4use ratatui::crossterm::event::{KeyCode, KeyEvent};
5use steer_core::app::{AppCommand, command::ApprovalType};
6use steer_core::error::Error as CoreError;
7use steer_tools::tools::BASH_TOOL_NAME;
8use steer_tools::tools::bash::BashParams;
9use tracing::debug;
10
11impl Tui {
12 pub async fn handle_approval_mode(&mut self, key: KeyEvent) -> Result<bool> {
13 if let Some(tool_call) = self.current_tool_approval.take() {
14 match key.code {
15 KeyCode::Char('y') | KeyCode::Char('Y') => {
16 self.client
18 .send_command(AppCommand::HandleToolResponse {
19 id: tool_call.id,
20 approval: ApprovalType::Once,
21 })
22 .await?;
23 self.input_mode = self.default_input_mode();
24 }
25 KeyCode::Char('a') | KeyCode::Char('A') => {
26 debug!(target: "handle_approval_mode", "Approving tool call with ID '{}' and name '{}'", tool_call.id, tool_call.name);
27 if tool_call.name == BASH_TOOL_NAME {
28 debug!(target: "handle_approval_mode", "(Always) Approving bash command with ID '{}'", tool_call.id);
29 let bash_params: BashParams =
31 serde_json::from_value(tool_call.parameters.clone()).map_err(|e| {
32 Error::Core(CoreError::Tool(
33 steer_tools::ToolError::InvalidParams(
34 "bash".to_string(),
35 e.to_string(),
36 )
37 .into(),
38 ))
39 })?;
40 self.client
42 .send_command(AppCommand::HandleToolResponse {
43 id: tool_call.id,
44 approval: ApprovalType::AlwaysBashPattern(
45 bash_params.command.clone(),
46 ),
47 })
48 .await?;
49 } else {
50 self.client
52 .send_command(AppCommand::HandleToolResponse {
53 id: tool_call.id,
54 approval: ApprovalType::AlwaysTool,
55 })
56 .await?;
57 }
58 self.input_mode = self.default_input_mode();
59 }
60 KeyCode::Char('l') | KeyCode::Char('L') => {
61 if tool_call.name == BASH_TOOL_NAME {
62 self.client
63 .send_command(AppCommand::HandleToolResponse {
64 id: tool_call.id,
65 approval: ApprovalType::AlwaysTool,
66 })
67 .await?;
68 self.input_mode = self.default_input_mode();
69 } else {
70 self.current_tool_approval = Some(tool_call);
72 }
73 }
74 KeyCode::Char('n') | KeyCode::Char('N') | KeyCode::Esc => {
75 self.client
77 .send_command(AppCommand::HandleToolResponse {
78 id: tool_call.id,
79 approval: ApprovalType::Denied,
80 })
81 .await?;
82 self.input_mode = self.default_input_mode();
83 }
84 _ => {
85 self.current_tool_approval = Some(tool_call);
87 }
88 }
89 } else {
90 self.input_mode = self.default_input_mode();
92 }
93 Ok(false)
94 }
95}