use serde_json::Value;
use crate::brain::agent::error::AgentError;
use crate::brain::provider::ProviderError;
const PENDING_CALL_MAX_CHARS: usize = 240;
pub(crate) fn describe_pending_calls(tool_uses: &[(String, String, Value)]) -> String {
tool_uses
.iter()
.map(|(_, name, input)| {
let args = serde_json::to_string(input).unwrap_or_default();
let full = format!("{name} {args}");
if full.chars().count() <= PENDING_CALL_MAX_CHARS {
full
} else {
let mut cut: String = full.chars().take(PENDING_CALL_MAX_CHARS - 1).collect();
cut.push('…');
cut
}
})
.collect::<Vec<_>>()
.join("; ")
}
pub(crate) fn loop_break_error(
guard: &str,
label: &str,
count: usize,
window: usize,
pending: &str,
) -> AgentError {
AgentError::Provider(ProviderError::AnnouncementLoop(format!(
"{guard}: '{label}' recurred {count}x in the last {window} steps; dropped call: {pending}"
)))
}
pub(crate) fn chain_exhausted(err: AgentError, providers_tried: u32) -> AgentError {
match err {
AgentError::Provider(ProviderError::AnnouncementLoop(msg)) => {
AgentError::Provider(ProviderError::AnnouncementLoop(format!(
"{msg}; every provider in the fallback chain ({providers_tried} tried) hit the \
same loop. Nothing is queued, say the word to resume"
)))
}
other => other,
}
}