fix: exempt agent__check_inbox and agent__task_list from loop

This commit is contained in:
Dark-Alex-17 committed 2026-09-16 11:07:10 -06:00
1 parent fa7f96e9e8
commit 8be9c8e152
1 file changed
+29 -4
+29 -4
View File
@@ -2518,13 +2518,13 @@ fn polyfill_cmd_name<T: AsRef<Path>>(cmd_name: &str, bin_dir: &[T]) -> String {
cmd_name cmd_name
} }
// Polling tools are expected to repeat; recording them would also let them const LOOP_TRACKER_EXEMPT_TOOLS: [&str; 6] = [
// break up detection of a real loop in the calls they interleave with.
const LOOP_TRACKER_EXEMPT_TOOLS: [&str; 4] = [
"job__check", "job__check",
"job__list", "job__list",
"agent__check", "agent__check",
"agent__list_running", "agent__list_running",
"agent__task_list",
"agent__check_inbox",
]; ];
fn is_loop_tracker_exempt(name: &str) -> bool { fn is_loop_tracker_exempt(name: &str) -> bool {
@@ -3328,10 +3328,12 @@ mod tests {
"job__list", "job__list",
"agent__check", "agent__check",
"agent__list_running", "agent__list_running",
"agent__task_list",
"agent__check_inbox",
] ]
.into_iter() .into_iter()
.collect(); .collect();
assert_eq!(LOOP_TRACKER_EXEMPT_TOOLS.len(), 4); assert_eq!(LOOP_TRACKER_EXEMPT_TOOLS.len(), 6);
assert_eq!(actual, expected); assert_eq!(actual, expected);
} }
@@ -3368,6 +3370,29 @@ mod tests {
assert!(tracker.check_loop(&x).is_some()); assert!(tracker.check_loop(&x).is_some());
} }
/// Zero-argument polls (`agent__check_inbox`, `agent__task_list`) are
/// byte-identical on every call, so the protocol-mandated "check your inbox
/// after each round" cadence must never read as a loop — even when the
/// polls are back-to-back and well past the repeat threshold.
#[test]
fn tracker_zero_arg_polls_never_trip_even_when_consecutive() {
for name in ["agent__check_inbox", "agent__task_list"] {
let mut tracker = ToolCallTracker::default();
let poll = call_with_args(name, json!({}));
for _ in 0..10 {
assert!(
tracker.check_loop(&poll).is_none(),
"{name} must never trip the loop tracker"
);
tracker.record_call(poll.clone());
}
assert!(
tracker.last_calls.is_empty(),
"{name} must not be recorded in the call history"
);
}
}
#[test] #[test]
fn tracker_non_exempt_behavior_unchanged() { fn tracker_non_exempt_behavior_unchanged() {
let mut tracker = ToolCallTracker::default(); let mut tracker = ToolCallTracker::default();