replace ContainerRuntime CLI to Bollard crate (default: docker socket)
ci/woodpecker/push/tests Pipeline was successful
ci/woodpecker/push/tests Pipeline was successful
limit tool result to open router tool response (with truncated info for ai) Hard kill if graceful shutdown is too long
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
//! Small text helpers shared by the modules that log what the model answered and
|
||||
//! bound what the tools return to it.
|
||||
|
||||
/// First `limit` characters of `text`, for logs.
|
||||
///
|
||||
/// Cuts on character boundaries, so the excerpt stays valid UTF-8, and marks a
|
||||
/// truncation with an ellipsis.
|
||||
pub fn excerpt(text: &str, limit: usize) -> String {
|
||||
let mut chars = text.chars();
|
||||
let excerpt = chars.by_ref().take(limit).collect::<String>();
|
||||
|
||||
if chars.next().is_some() {
|
||||
return format!("{excerpt}…");
|
||||
}
|
||||
|
||||
excerpt
|
||||
}
|
||||
|
||||
/// Truncates `text` in place to at most `limit` bytes, cutting on a character
|
||||
/// boundary so the result stays valid UTF-8.
|
||||
///
|
||||
/// Returns `true` when something was dropped.
|
||||
pub fn truncate_bytes(text: &mut String, limit: usize) -> bool {
|
||||
if text.len() <= limit {
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut end = limit;
|
||||
while !text.is_char_boundary(end) {
|
||||
end -= 1;
|
||||
}
|
||||
|
||||
text.truncate(end);
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn a_short_text_is_kept_as_is() {
|
||||
assert_eq!(excerpt("abc", 3), "abc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_long_text_is_truncated_and_marked() {
|
||||
assert_eq!(excerpt("abcdef", 3), "abc…");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncation_cuts_on_character_boundaries() {
|
||||
assert_eq!(excerpt("ééé", 2), "éé…");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_short_text_is_not_truncated() {
|
||||
let mut text = String::from("abc");
|
||||
|
||||
assert!(!truncate_bytes(&mut text, 3));
|
||||
assert_eq!(text, "abc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_long_text_is_truncated_within_the_limit() {
|
||||
let mut text = String::from("abcdef");
|
||||
|
||||
assert!(truncate_bytes(&mut text, 4));
|
||||
assert_eq!(text, "abcd");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_truncation_never_splits_a_character() {
|
||||
let mut text = String::from("ééé");
|
||||
|
||||
// The limit falls in the middle of the second `é`: it is dropped.
|
||||
assert!(truncate_bytes(&mut text, 3));
|
||||
assert_eq!(text, "é");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user