bxcore, brokerd, loopd: an invalid-arguments denial says why

Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
2026-09-27 19:08:42 -07:00
co-authored by ornith-1.5-35b-a3b
parent 89a50bc3c6
commit de60c9e13a
21 changed files with 520 additions and 33 deletions
@@ -0,0 +1 @@
{"v":1,"id":9,"final":true,"msg":{"kind":"tool_response","body":{"status":"denied","reason":"invalid_arguments","detail":"invalid argument shape: unknown field `file`, expected `text`"}}}
+1
View File
@@ -68,6 +68,7 @@ fn envelopes_reject_unknown_keys_at_every_depth() {
"tool_response_result.json",
"tool_response_failed.json",
"tool_response_denied.json",
"tool_response_denied_detail.json",
"error.json",
"turn.json",
"turn_event_tool_result.json",
+25
View File
@@ -94,10 +94,35 @@ fn tool_response_failed() {
fn tool_response_denied() {
let body = ToolResponse::Denied {
reason: DenyReason::TaintTooHigh,
detail: None,
};
check("tool_response_denied.json", response(9, true, body));
}
/// A detail is written only when there is one, so the fixture above has no `detail` key.
#[test]
fn tool_response_denied_with_a_detail() {
let body = ToolResponse::Denied {
reason: DenyReason::InvalidArguments,
detail: Some("invalid argument shape: unknown field `file`, expected `text`".to_string()),
};
check("tool_response_denied_detail.json", response(9, true, body));
}
#[test]
fn a_detail_must_be_a_string() {
let good = fixture("tool_response_denied_detail.json");
assert!(serde_json::from_str::<Envelope>(&good).is_ok());
let at = good.find("\"detail\":").unwrap();
for value in ["7", "[\"a\"]", "{}", "true"] {
let bad = format!("{}\"detail\":{value}}}}}}}", &good[..at]);
assert!(
serde_json::from_str::<Envelope>(&bad).is_err(),
"accepted {bad}"
);
}
}
#[test]
fn error_message() {
let body = WireError {