pub(super) fn agent_primitive_cancelled_tool(
tool_name: &str,
tool_call_id: &str,
tool_args: &serde_json::Value,
reason: &str,
executor: Option<serde_json::Value>,
execution_duration_ms: u64,
approval_status: Option<&'static str>,
) -> serde_json::Value {
let rendered = if reason.is_empty() {
format!("[cancelled in-flight: {tool_name}]")
} else {
format!("[cancelled in-flight: {tool_name}] {reason}")
};
let observation = format!(
"[cancelled call to {name}]\n{reason}\n[end of {name} cancellation]\n",
name = tool_name,
reason = if reason.is_empty() {
"cancelled by host"
} else {
reason
},
);
let error_message = if reason.is_empty() {
format!("tool call cancelled in-flight: {tool_name}")
} else {
format!("tool call cancelled in-flight: {reason}")
};
let mut result = super::agent_primitive_unexecuted_tool_base(
tool_name,
tool_call_id,
tool_args,
"cancelled",
rendered,
observation,
error_message,
);
if let Some(obj) = result.as_object_mut() {
obj.insert(
"executor".to_string(),
executor.unwrap_or(serde_json::Value::Null),
);
obj.insert("approval".to_string(), serde_json::json!(approval_status));
obj.insert(
"execution_duration_ms".to_string(),
serde_json::json!(execution_duration_ms),
);
obj.insert("cancelled".to_string(), serde_json::Value::Bool(true));
obj.insert("cancellation_reason".to_string(), serde_json::json!(reason));
}
result
}
pub(super) fn with_applied_mutations(
mut result: serde_json::Value,
session_id: &str,
tool_call_id: &str,
) -> serde_json::Value {
let applied = crate::tool_call_mutations::take(session_id, tool_call_id);
if let Some(obj) = result.as_object_mut().filter(|_| !applied.is_empty()) {
obj.insert(
"mutation_status".to_string(),
serde_json::json!(crate::agent_events::ToolMutationStatus::Applied.as_str()),
);
obj.insert("changed_paths".to_string(), serde_json::json!(applied));
}
result
}