Add LLM stream timeout and debug logs
All checks were successful
BotServer CI/CD / build (push) Successful in 4m8s

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2026-04-14 00:55:43 -03:00
parent da9facf036
commit 301a7dda33
3 changed files with 45 additions and 27 deletions

View file

@ -859,7 +859,17 @@ impl BotOrchestrator {
} }
} }
while let Some(chunk) = stream_rx.recv().await { let stream_timeout = tokio::time::Duration::from_secs(60);
'stream_loop: loop {
let chunk_result = tokio::time::timeout(stream_timeout, stream_rx.recv()).await;
let chunk = match chunk_result {
Ok(Some(c)) => c,
Ok(None) => break 'stream_loop,
Err(_) => {
error!("LLM stream timeout after {}s - aborting response", stream_timeout.as_secs());
break 'stream_loop
}
};
// ===== GENERIC TOOL EXECUTION ===== // ===== GENERIC TOOL EXECUTION =====
// Add chunk to tool_call_buffer and try to parse // Add chunk to tool_call_buffer and try to parse

View file

@ -431,7 +431,7 @@ match result {
trace!("start_monitoring: calling check_for_changes..."); trace!("start_monitoring: calling check_for_changes...");
trace!("Calling initial check_for_changes..."); trace!("Calling initial check_for_changes...");
match tokio::time::timeout(Duration::from_secs(300), self.check_for_changes()).await { match tokio::time::timeout(Duration::from_secs(12), self.check_for_changes()).await {
Ok(Ok(_)) => { Ok(Ok(_)) => {
self.consecutive_failures.store(0, Ordering::Relaxed); self.consecutive_failures.store(0, Ordering::Relaxed);
} }
@ -514,7 +514,7 @@ match result {
debug!("[DRIVE_MONITOR] About to call check_for_changes for bot {}", self_clone.bot_id); debug!("[DRIVE_MONITOR] About to call check_for_changes for bot {}", self_clone.bot_id);
// Add timeout to prevent hanging // Add timeout to prevent hanging
match tokio::time::timeout(Duration::from_secs(300), self_clone.check_for_changes()).await { match tokio::time::timeout(Duration::from_secs(12), self_clone.check_for_changes()).await {
Ok(Ok(_)) => { Ok(Ok(_)) => {
let prev_failures = let prev_failures =
self_clone.consecutive_failures.swap(0, Ordering::Relaxed); self_clone.consecutive_failures.swap(0, Ordering::Relaxed);

View file

@ -438,6 +438,7 @@ impl LLMProvider for OpenAIClient {
} }
} }
info!("LLM: Sending request to {}", full_url);
let response = self let response = self
.client .client
.post(&full_url) .post(&full_url)
@ -445,6 +446,7 @@ impl LLMProvider for OpenAIClient {
.json(&request_body) .json(&request_body)
.send() .send()
.await?; .await?;
info!("LLM: Response received with status {}", response.status());
let status = response.status(); let status = response.status();
if status != reqwest::StatusCode::OK { if status != reqwest::StatusCode::OK {
@ -465,8 +467,13 @@ impl LLMProvider for OpenAIClient {
// Accumulate tool calls here because OpenAI streams them in fragments // Accumulate tool calls here because OpenAI streams them in fragments
let mut active_tool_calls: Vec<serde_json::Value> = Vec::new(); let mut active_tool_calls: Vec<serde_json::Value> = Vec::new();
let mut chunk_count = 0u32;
while let Some(chunk_result) = stream.next().await { while let Some(chunk_result) = stream.next().await {
chunk_count += 1;
if chunk_count <= 5 || chunk_count % 50 == 0 {
info!("LLM: Received chunk #{}", chunk_count);
}
let chunk = chunk_result?; let chunk = chunk_result?;
let chunk_str = String::from_utf8_lossy(&chunk); let chunk_str = String::from_utf8_lossy(&chunk);
for line in chunk_str.lines() { for line in chunk_str.lines() {
@ -537,6 +544,7 @@ let content = data["choices"][0]["delta"]["content"].as_str();
} }
} }
info!("LLM: Stream complete, sent {} chunks", chunk_count);
Ok(()) Ok(())
} }