Sends a [crate::api_client::ApiClient::send_message] request to the backend and consumes the response stream. In order to handle sigints while also keeping track of metadata about how the response stream was handled, we need an extra parameter: `request_metadata_lock` - Updated with the [RequestMetadata] once it has been received (either though a successful request, or on an error).
(
&mut self,
os: &mut Os,
state: crate::api_client::model::ConversationState,
request_metadata_lock: Arc<Mutex<Option<RequestMetadata>>>,
)
| 2810 | /// * `request_metadata_lock` - Updated with the [RequestMetadata] once it has been received |
| 2811 | /// (either though a successful request, or on an error). |
| 2812 | async fn handle_response( |
| 2813 | &mut self, |
| 2814 | os: &mut Os, |
| 2815 | state: crate::api_client::model::ConversationState, |
| 2816 | request_metadata_lock: Arc<Mutex<Option<RequestMetadata>>>, |
| 2817 | ) -> Result<ChatState, ChatError> { |
| 2818 | let mut rx = self.send_message(os, state, request_metadata_lock, None).await?; |
| 2819 | |
| 2820 | let request_id = rx.request_id().map(String::from); |
| 2821 | |
| 2822 | let mut buf = String::new(); |
| 2823 | let mut offset = 0; |
| 2824 | let mut ended = false; |
| 2825 | let terminal_width = match self.wrap { |
| 2826 | Some(WrapMode::Never) => None, |
| 2827 | Some(WrapMode::Always) => Some(self.terminal_width()), |
| 2828 | Some(WrapMode::Auto) | None => { |
| 2829 | if std::io::stdout().is_terminal() { |
| 2830 | Some(self.terminal_width()) |
| 2831 | } else { |
| 2832 | None |
| 2833 | } |
| 2834 | }, |
| 2835 | }; |
| 2836 | |
| 2837 | let mut state = ParseState::new( |
| 2838 | terminal_width, |
| 2839 | os.database.settings.get_bool(Setting::ChatDisableMarkdownRendering), |
| 2840 | ); |
| 2841 | let mut response_prefix_printed = false; |
| 2842 | |
| 2843 | let mut tool_uses = Vec::new(); |
| 2844 | let mut tool_name_being_recvd: Option<String> = None; |
| 2845 | |
| 2846 | if self.spinner.is_some() { |
| 2847 | drop(self.spinner.take()); |
| 2848 | queue!( |
| 2849 | self.stderr, |
| 2850 | terminal::Clear(terminal::ClearType::CurrentLine), |
| 2851 | cursor::MoveToColumn(0), |
| 2852 | )?; |
| 2853 | } |
| 2854 | |
| 2855 | loop { |
| 2856 | match rx.recv().await { |
| 2857 | Some(Ok(msg_event)) => { |
| 2858 | trace!("Consumed: {:?}", msg_event); |
| 2859 | |
| 2860 | match msg_event { |
| 2861 | parser::ResponseEvent::ToolUseStart { name } => { |
| 2862 | // We need to flush the buffer here, otherwise text will not be |
| 2863 | // printed while we are receiving tool use events. |
| 2864 | buf.push('\n'); |
| 2865 | tool_name_being_recvd = Some(name); |
| 2866 | }, |
| 2867 | parser::ResponseEvent::AssistantText(text) => { |
| 2868 | if self.stdout.should_send_structured_event { |
| 2869 | if !response_prefix_printed && !text.trim().is_empty() { |
nothing calls this directly
no test coverage detected