#[allow(clippy::wildcard_imports)]
use super::super::*;
pub(super) fn append_rules_self_heal_status(
result_text: String,
heal_result: Option<&lean_ctx::rules_inject::InjectResult>,
) -> String {
let Some(heal_result) = heal_result else {
return result_text;
};
if !heal_result.errors.is_empty() || heal_result.updated.is_empty() {
return result_text;
}
format!(
"{result_text}\n\n[RULES AUTO-UPDATED] Your lean-ctx rules were written by \
an older version and have been refreshed on disk. Start a new session to \
load them for full compatibility."
)
}
pub(in crate::server) fn roots_list_failure_is_permanent(e: &rmcp::ServiceError) -> bool {
matches!(
e,
rmcp::ServiceError::McpError(mcp)
if mcp.code == rmcp::model::ErrorCode::METHOD_NOT_FOUND
)
}
pub(in crate::server) fn finalize_call_result(
result_text: &str,
shell_outcome: Option<crate::server::tool_trait::ShellOutcome>,
) -> CallToolResult {
let mut result = CallToolResult::success(vec![ContentBlock::text(result_text.to_owned())]);
if let Some(outcome) = shell_outcome {
if matches!(
outcome,
crate::server::tool_trait::ShellOutcome::Background(_)
| crate::server::tool_trait::ShellOutcome::BackgroundLookupError(_)
) {
result.structured_content = outcome.structured();
if outcome.is_error() {
result.is_error = Some(true);
}
} else if is_shell_error(&outcome, result_text) {
result.is_error = Some(true);
result.structured_content = outcome.structured();
}
}
result
}
pub(in crate::server) fn is_shell_error(
outcome: &crate::server::tool_trait::ShellOutcome,
output: &str,
) -> bool {
match outcome {
crate::server::tool_trait::ShellOutcome::Exit(0) => false,
crate::server::tool_trait::ShellOutcome::Exit(1) => {
output.trim().is_empty() || output.trim().starts_with("[exit:")
}
crate::server::tool_trait::ShellOutcome::Exit(124) => {
crate::server::execute::output_before_timeout_marker(output).is_none_or(str::is_empty)
}
crate::server::tool_trait::ShellOutcome::Exit(_)
| crate::server::tool_trait::ShellOutcome::Blocked
| crate::server::tool_trait::ShellOutcome::BackgroundLookupError(_) => true,
crate::server::tool_trait::ShellOutcome::Background(outcome) => outcome.is_error,
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::server::tool_trait::ShellOutcome;
#[test]
fn signal_termination_with_output_is_error() {
let r = finalize_call_result(
"partial output\n[exit:143 — SIGTERM]",
Some(ShellOutcome::Exit(143)),
);
assert_eq!(r.is_error, Some(true));
}
}