1- use std:: time:: Instant ;
1+ use std:: time:: {
2+ Duration ,
3+ Instant ,
4+ } ;
25
36use eyre:: Result ;
47use fig_api_client:: clients:: SendMessageOutput ;
@@ -66,6 +69,7 @@ pub enum RecvErrorKind {
6669 tool_use_id : String ,
6770 name : String ,
6871 message : Box < AssistantMessage > ,
72+ time_elapsed : Duration ,
6973 } ,
7074}
7175
@@ -180,29 +184,29 @@ impl ResponseParser {
180184 /// The arguments are the fields from the first [ChatResponseStream::ToolUseEvent] consumed.
181185 async fn parse_tool_use ( & mut self , id : String , name : String ) -> Result < AssistantToolUse , RecvError > {
182186 let mut tool_string = String :: new ( ) ;
183- let mut stop_seen = false ;
184187 let start = Instant :: now ( ) ;
185188 while let Some ( ChatResponseStream :: ToolUseEvent { .. } ) = self . peek ( ) . await ? {
186189 if let Some ( ChatResponseStream :: ToolUseEvent { input, stop, .. } ) = self . next ( ) . await ? {
187190 if let Some ( i) = input {
188191 tool_string. push_str ( & i) ;
189192 }
190193 if let Some ( true ) = stop {
191- stop_seen = true ;
192194 break ;
193195 }
194196 }
195197 }
196198 let args = match serde_json:: from_str ( & tool_string) {
197199 Ok ( args) => args,
198200 Err ( err) => {
199- // If the stream ended before we saw the final tool use event (and thus failed
200- // deserializing the tool use), this is most likely due to the backend dropping the
201- // connection. The tool was too large!
202- if self . peek ( ) . await ?. is_none ( ) && !stop_seen {
201+ // If we failed deserializing after waiting for a long time, then this is most
202+ // likely bedrock responding with a stop event for some reason without actually
203+ // including the tool contents. Essentially, the tool was too large.
204+ // Timeouts have been seen as short as ~1 minute, so setting the time to 30.
205+ let time_elapsed = start. elapsed ( ) ;
206+ if self . peek ( ) . await ?. is_none ( ) && time_elapsed > Duration :: from_secs ( 30 ) {
203207 error ! (
204208 "Received an unexpected end of stream after spending ~{}s receiving tool events" ,
205- Instant :: now ( ) . duration_since ( start ) . as_secs_f64( )
209+ time_elapsed . as_secs_f64( )
206210 ) ;
207211 self . tool_uses . push ( AssistantToolUse {
208212 id : id. clone ( ) ,
@@ -211,18 +215,14 @@ impl ResponseParser {
211215 [ (
212216 "key" . to_string ( ) ,
213217 serde_json:: Value :: String (
214- "fake tool use args - actual tool use was too large to include" . to_string ( ) ,
218+ "WARNING: the actual tool use arguments were too complicated to be generated"
219+ . to_string ( ) ,
215220 ) ,
216221 ) ]
217222 . into_iter ( )
218223 . collect ( ) ,
219224 ) ,
220225 } ) ;
221- // let message = Box::new(AssistantMessage {
222- // message_id: Some(self.message_id.clone()),
223- // content: std::mem::take(&mut self.assistant_text),
224- // tool_uses: Some(self.tool_uses.clone().into_iter().map(Into::into).collect()),
225- // });
226226 let message = Box :: new ( AssistantMessage :: new_tool_use (
227227 Some ( self . message_id . clone ( ) ) ,
228228 std:: mem:: take ( & mut self . assistant_text ) ,
@@ -232,6 +232,7 @@ impl ResponseParser {
232232 tool_use_id : id,
233233 name,
234234 message,
235+ time_elapsed,
235236 } ) ) ;
236237 } else {
237238 return Err ( self . error ( err) ) ;
0 commit comments