use std::borrow::Cow;
pub const DEFAULT_MAX_OUTPUT_BYTES: usize = 50_000;
const _: () = assert!(DEFAULT_MAX_OUTPUT_BYTES == 50_000);
const TRUNCATION_MARKER: &str = "\n[…truncated by SQRY_MCP_MAX_OUTPUT_BYTES…]";
#[must_use]
pub fn max_output_bytes() -> usize {
std::env::var("SQRY_MCP_MAX_OUTPUT_BYTES")
.ok()
.and_then(|v| v.parse::<usize>().ok())
.unwrap_or(DEFAULT_MAX_OUTPUT_BYTES)
}
#[must_use]
pub fn truncate_response(s: &str, cap: usize) -> Cow<'_, str> {
if s.len() <= cap {
return Cow::Borrowed(s);
}
let end = s
.char_indices()
.map(|(i, c)| i + c.len_utf8())
.take_while(|end| *end <= cap)
.last()
.unwrap_or(0);
Cow::Owned(format!("{}{TRUNCATION_MARKER}", &s[..end]))
}
#[cfg(test)]
mod tests {
use super::*;
use serial_test::serial;
#[test]
#[serial]
fn max_output_bytes_default_is_50_000() {
unsafe {
std::env::remove_var("SQRY_MCP_MAX_OUTPUT_BYTES");
}
assert_eq!(max_output_bytes(), 50_000);
assert_eq!(max_output_bytes(), DEFAULT_MAX_OUTPUT_BYTES);
}
#[test]
#[serial]
fn max_output_bytes_reads_env_var() {
unsafe {
std::env::set_var("SQRY_MCP_MAX_OUTPUT_BYTES", "10");
}
let v = max_output_bytes();
unsafe {
std::env::remove_var("SQRY_MCP_MAX_OUTPUT_BYTES");
}
assert_eq!(v, 10);
}
#[test]
#[serial]
fn max_output_bytes_invalid_falls_back_to_default() {
unsafe {
std::env::set_var("SQRY_MCP_MAX_OUTPUT_BYTES", "not-a-number");
}
let v = max_output_bytes();
unsafe {
std::env::remove_var("SQRY_MCP_MAX_OUTPUT_BYTES");
}
assert_eq!(v, DEFAULT_MAX_OUTPUT_BYTES);
}
#[test]
fn truncate_response_under_cap_is_borrowed_passthrough() {
let s = "small payload";
let out = truncate_response(s, 1024);
assert_eq!(out.as_ref(), s);
assert!(matches!(out, Cow::Borrowed(_)));
}
#[test]
fn truncate_response_over_cap_emits_marker() {
let big = "a".repeat(100);
let out = truncate_response(&big, 10);
assert!(
out.ends_with("[…truncated by SQRY_MCP_MAX_OUTPUT_BYTES…]"),
"expected truncation marker, got {out:?}"
);
let body_len = out.len() - TRUNCATION_MARKER.len();
assert!(
body_len <= 10,
"truncated body exceeded cap: {body_len} > 10"
);
}
#[test]
fn truncate_response_at_exact_cap_is_passthrough() {
let s = "0123456789"; let out = truncate_response(s, 10);
assert_eq!(out.as_ref(), s);
assert!(matches!(out, Cow::Borrowed(_)));
}
#[test]
fn truncate_response_utf8_boundary_safe() {
let s = "ééééé"; let out = truncate_response(s, 3);
let prefix = out
.as_ref()
.strip_suffix(TRUNCATION_MARKER)
.expect("marker must be present");
assert!(
std::str::from_utf8(prefix.as_bytes()).is_ok(),
"truncated prefix must be valid UTF-8: {prefix:?}"
);
assert_eq!(prefix, "é");
}
}