Skip to content

Commit b7620e9

Browse files
fix: various bugs with chat (#331)
1 parent e44d94a commit b7620e9

File tree

3 files changed

+47
-15
lines changed

3 files changed

+47
-15
lines changed

crates/chat-cli/src/cli/chat/cli/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,15 @@ pub enum ContextSubcommand {
5050
/// Include even if matched files exceed size limits
5151
#[arg(short, long)]
5252
force: bool,
53+
#[arg(required = true)]
5354
paths: Vec<String>,
5455
},
5556
/// Remove specified rules from current profile
5657
Remove {
5758
/// Remove specified rules globally
5859
#[arg(short, long)]
5960
global: bool,
61+
#[arg(required = true)]
6062
paths: Vec<String>,
6163
},
6264
/// Remove all rules from current profile

crates/chat-cli/src/cli/chat/cli/tools.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,15 @@ pub enum ToolsSubcommand {
152152
/// Show the input schema for all available tools
153153
Schema,
154154
/// Trust a specific tool or tools for the session
155-
Trust { tool_names: Vec<String> },
155+
Trust {
156+
#[arg(required = true)]
157+
tool_names: Vec<String>,
158+
},
156159
/// Revert a tool or tools to per-request confirmation
157-
Untrust { tool_names: Vec<String> },
160+
Untrust {
161+
#[arg(required = true)]
162+
tool_names: Vec<String>,
163+
},
158164
/// Trust all tools (equivalent to deprecated /acceptall)
159165
TrustAll,
160166
/// Reset all tools to default permission levels

crates/chat-cli/src/cli/chat/mod.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,10 @@ pub enum ChatError {
402402
Interrupted { tool_uses: Option<Vec<QueuedTool>> },
403403
#[error(transparent)]
404404
GetPromptError(#[from] GetPromptError),
405+
#[error(
406+
"Tool approval required but --no-interactive was specified. Use --trust-all-tools to automatically approve tools."
407+
)]
408+
NonInteractiveToolApproval,
405409
}
406410

407411
impl ChatError {
@@ -415,6 +419,7 @@ impl ChatError {
415419
ChatError::Custom(_) => None,
416420
ChatError::Interrupted { .. } => None,
417421
ChatError::GetPromptError(_) => None,
422+
ChatError::NonInteractiveToolApproval => None,
418423
}
419424
}
420425
}
@@ -430,6 +435,7 @@ impl ReasonCode for ChatError {
430435
ChatError::Interrupted { .. } => "Interrupted".to_string(),
431436
ChatError::GetPromptError(_) => "GetPromptError".to_string(),
432437
ChatError::Auth(_) => "AuthError".to_string(),
438+
ChatError::NonInteractiveToolApproval => "NonInteractiveToolApproval".to_string(),
433439
}
434440
}
435441
}
@@ -573,10 +579,16 @@ impl ChatSession {
573579
let ctrl_c_stream = ctrl_c();
574580
let result = match self.inner.take().expect("state must always be Some") {
575581
ChatState::PromptUser { skip_printing_tools } => {
576-
if !self.interactive {
577-
self.inner = Some(ChatState::Exit);
578-
return Ok(());
579-
}
582+
match (self.interactive, self.tool_uses.is_empty()) {
583+
(false, true) => {
584+
self.inner = Some(ChatState::Exit);
585+
return Ok(());
586+
},
587+
(false, false) => {
588+
return Err(ChatError::NonInteractiveToolApproval);
589+
},
590+
_ => (),
591+
};
580592

581593
self.prompt_user(os, skip_printing_tools).await
582594
},
@@ -862,6 +874,7 @@ impl Default for ChatState {
862874
impl ChatSession {
863875
async fn spawn(&mut self, os: &mut Os) -> Result<()> {
864876
let is_small_screen = self.terminal_width() < GREETING_BREAK_POINT;
877+
let mut interactive_text: Vec<u8> = Vec::new();
865878
if os
866879
.database
867880
.settings
@@ -876,20 +889,20 @@ impl ChatSession {
876889
},
877890
};
878891

879-
execute!(self.stderr, style::Print(welcome_text), style::Print("\n\n"),)?;
892+
execute!(interactive_text, style::Print(welcome_text), style::Print("\n\n"),)?;
880893

881894
let tip = ROTATING_TIPS[usize::try_from(rand::random::<u32>()).unwrap_or(0) % ROTATING_TIPS.len()];
882895
if is_small_screen {
883896
// If the screen is small, print the tip in a single line
884897
execute!(
885-
self.stderr,
898+
interactive_text,
886899
style::Print("💡 ".to_string()),
887900
style::Print(tip),
888901
style::Print("\n")
889902
)?;
890903
} else {
891904
draw_box(
892-
&mut self.stderr,
905+
&mut interactive_text,
893906
"Did you know?",
894907
tip,
895908
GREETING_BREAK_POINT,
@@ -898,7 +911,7 @@ impl ChatSession {
898911
}
899912

900913
execute!(
901-
self.stderr,
914+
interactive_text,
902915
style::Print("\n"),
903916
style::Print(match is_small_screen {
904917
true => SMALL_SCREEN_POPULAR_SHORTCUTS,
@@ -911,24 +924,27 @@ impl ChatSession {
911924
.dark_grey()
912925
)
913926
)?;
914-
execute!(self.stderr, style::Print("\n"), style::SetForegroundColor(Color::Reset))?;
927+
execute!(
928+
interactive_text,
929+
style::Print("\n"),
930+
style::SetForegroundColor(Color::Reset)
931+
)?;
915932
}
916933

917934
if self.all_tools_trusted() {
918935
queue!(
919-
self.stderr,
936+
interactive_text,
920937
style::Print(format!(
921938
"{}{TRUST_ALL_TEXT}\n\n",
922939
if !is_small_screen { "\n" } else { "" }
923940
))
924941
)?;
925942
}
926-
self.stderr.flush()?;
927943

928944
if let Some(ref id) = self.conversation.model {
929945
if let Some(model_option) = MODEL_OPTIONS.iter().find(|option| option.model_id == *id) {
930946
execute!(
931-
self.stderr,
947+
interactive_text,
932948
style::SetForegroundColor(Color::Cyan),
933949
style::Print(format!("🤖 You are chatting with {}\n", model_option.name)),
934950
style::SetForegroundColor(Color::Reset),
@@ -937,6 +953,11 @@ impl ChatSession {
937953
}
938954
}
939955

956+
if self.interactive {
957+
self.stderr.write_all(&interactive_text)?;
958+
self.stderr.flush()?;
959+
}
960+
940961
if let Some(user_input) = self.initial_input.take() {
941962
self.inner = Some(ChatState::HandleInput { input: user_input });
942963
}
@@ -1397,7 +1418,10 @@ impl ChatSession {
13971418
queue!(self.stderr, style::SetForegroundColor(Color::Reset))?;
13981419
queue!(self.stderr, cursor::Hide)?;
13991420
execute!(self.stderr, style::Print("\n"))?;
1400-
self.spinner = Some(Spinner::new(Spinners::Dots, "Thinking...".to_owned()));
1421+
1422+
if self.interactive {
1423+
self.spinner = Some(Spinner::new(Spinners::Dots, "Thinking...".to_owned()));
1424+
}
14011425

14021426
Ok(ChatState::HandleResponseStream(
14031427
os.client.send_message(conv_state).await?,

0 commit comments

Comments
 (0)