| 821 | } |
| 822 | |
| 823 | pub async fn next(&mut self, os: &mut Os) -> Result<(), ChatError> { |
| 824 | // Update conversation state with new tool information |
| 825 | self.conversation.update_state(false).await; |
| 826 | |
| 827 | let mut ctrl_c_stream = self.ctrlc_rx.resubscribe(); |
| 828 | let result = match self.inner.take().expect("state must always be Some") { |
| 829 | ChatState::PromptUser { skip_printing_tools } => { |
| 830 | match (self.interactive, self.tool_uses.is_empty()) { |
| 831 | (false, true) => { |
| 832 | self.inner = Some(ChatState::Exit); |
| 833 | return Ok(()); |
| 834 | }, |
| 835 | (false, false) => { |
| 836 | return Err(ChatError::NonInteractiveToolApproval); |
| 837 | }, |
| 838 | _ => (), |
| 839 | }; |
| 840 | |
| 841 | self.prompt_user(os, skip_printing_tools).await |
| 842 | }, |
| 843 | ChatState::HandleInput { input } => { |
| 844 | tokio::select! { |
| 845 | res = self.handle_input(os, input) => res, |
| 846 | Ok(_) = ctrl_c_stream.recv() => Err(ChatError::Interrupted { tool_uses: Some(self.tool_uses.clone()) }) |
| 847 | } |
| 848 | }, |
| 849 | ChatState::CompactHistory { |
| 850 | prompt, |
| 851 | show_summary, |
| 852 | strategy, |
| 853 | } => { |
| 854 | // compact_history manages ctrl+c handling |
| 855 | self.compact_history(os, prompt, show_summary, strategy).await |
| 856 | }, |
| 857 | ChatState::ExecuteTools => { |
| 858 | let tool_uses_clone = self.tool_uses.clone(); |
| 859 | tokio::select! { |
| 860 | res = self.tool_use_execute(os) => res, |
| 861 | Ok(_) = ctrl_c_stream.recv() => Err(ChatError::Interrupted { tool_uses: Some(tool_uses_clone) }) |
| 862 | } |
| 863 | }, |
| 864 | ChatState::ValidateTools { tool_uses } => { |
| 865 | tokio::select! { |
| 866 | res = self.validate_tools(os, tool_uses) => res, |
| 867 | Ok(_) = ctrl_c_stream.recv() => Err(ChatError::Interrupted { tool_uses: None }) |
| 868 | } |
| 869 | }, |
| 870 | ChatState::HandleResponseStream(conversation_state) => { |
| 871 | let request_metadata: Arc<Mutex<Option<RequestMetadata>>> = Arc::new(Mutex::new(None)); |
| 872 | let request_metadata_clone = Arc::clone(&request_metadata); |
| 873 | |
| 874 | tokio::select! { |
| 875 | res = self.handle_response(os, conversation_state, request_metadata_clone) => res, |
| 876 | Ok(_) = ctrl_c_stream.recv() => { |
| 877 | debug!(?request_metadata, "ctrlc received"); |
| 878 | // Wait for handle_response to finish handling the ctrlc. |
| 879 | tokio::time::sleep(Duration::from_millis(5)).await; |
| 880 | if let Some(request_metadata) = request_metadata.lock().await.take() { |