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
+47
View File
@@ -31,6 +31,7 @@ fn tool_events(events: &[TurnEvent]) -> Vec<String> {
fn a_denial_is_a_fixed_sentence_for_the_model_and_an_event_for_the_owner() {
let s = setup(vec![ToolResponse::Denied {
reason: DenyReason::TaintTooHigh,
detail: None,
}]);
s.server.route(
CHAT,
@@ -78,10 +79,55 @@ fn a_denial_is_a_fixed_sentence_for_the_model_and_an_event_for_the_owner() {
);
}
/// The broker's detail reaches the model, in the log and in the next request; the owner's event
/// is the same as for any denial.
#[test]
fn an_invalid_call_tells_the_model_why() {
let s = setup(vec![ToolResponse::Denied {
reason: DenyReason::InvalidArguments,
detail: Some("invalid path: n/a".to_string()),
}]);
s.server.route(
CHAT,
vec![Reply::fixture("tool_call"), Reply::fixture("plain")],
);
let mut session = s.session("a");
let (result, events) = s.turn(&mut session, "x");
assert!(result.is_ok(), "{result:?}");
let want = "Denied: the arguments are not valid for this tool: invalid path: n/a.";
match &session.records()[4] {
LogRecord::ToolResult {
content,
class,
untrusted,
truncated,
..
} => {
assert_eq!(content, want);
assert_eq!(
(*class, *untrusted, *truncated),
(DataClass::Public, false, false)
);
}
other => panic!("{other:?}"),
}
assert_eq!(
tool_events(&events),
[
"started read_file",
"denied read_file InvalidArguments",
"result read_file"
]
);
let m2 = s.server.requests_to(CHAT)[1].json();
assert_eq!(m2["messages"][3]["content"], want);
}
#[test]
fn a_denied_call_tool_names_the_target_tool_in_the_denial() {
let s = setup(vec![ToolResponse::Denied {
reason: DenyReason::NoGrant,
detail: None,
}]);
s.server.route(
CHAT,
@@ -158,6 +204,7 @@ fn a_pending_approval_that_ends_in_a_refusal() {
pending(7, "2026-09-18T12:15:00.000Z"),
ToolResponse::Denied {
reason: DenyReason::ApprovalRefused,
detail: None,
},
]);
s.server.route(