use crate::agent_events::SideEffectCeilingDetails;
pub(super) fn denied_tool_result(tool_name: &str, reason: impl Into<String>) -> serde_json::Value {
let reason = reason.into();
let allowed = crate::orchestration::current_allowed_tool_names();
let available_clause = if allowed.is_empty() {
String::new()
} else {
format!(" Available tools: {}.", allowed.join(", "))
};
let next_step = format!(
"The `{tool_name}` tool is not permitted right now. Do not retry the same call. \
Make progress with the tools you are allowed to use, or if this capability is \
essential, briefly tell the user what you need permission for and why.\
{available_clause}"
);
serde_json::json!({
"error": "permission_denied",
"tool": tool_name,
"reason": reason,
"next_step": next_step,
})
}
pub(super) fn side_effect_ceiling_tool_result(
tool_name: &str,
reason: impl Into<String>,
details: &SideEffectCeilingDetails,
) -> serde_json::Value {
let reason = reason.into();
let next_step = format!(
"`{tool_name}` requires side-effect level `{}`, but this session permits only through `{}`. \
Do not retry the same call. Choose a non-mutating approach, or ask the operator to raise \
the session side-effect ceiling to `{}` before retrying.",
details.required_level.as_str(),
details.ceiling.as_str(),
details.required_level.as_str(),
);
serde_json::json!({
"error": "permission_denied",
"tool": tool_name,
"reason": reason,
"next_step": next_step,
})
}