diff --git a/crates/goose/tests/repetition_inspector_tests.rs b/crates/goose/tests/repetition_inspector_tests.rs new file mode 100644 index 000000000000..a0ca7a7f6862 --- /dev/null +++ b/crates/goose/tests/repetition_inspector_tests.rs @@ -0,0 +1,33 @@ +use goose::tool_monitor::{RepetitionInspector, ToolCall}; +use serde_json::json; + +// This test targets RepetitionInspector::check_tool_call +// It verifies that: +// - consecutive identical tool calls are allowed up to max_repetitions times +// - the (max_repetitions + 1)th identical call is denied (returns false) +// - changing the parameters resets the repetition count and allows the call +#[test] +fn test_repetition_inspector_denies_after_exceeding_and_resets_on_param_change() { + // Allow at most 2 consecutive identical calls + let mut inspector = RepetitionInspector::new(Some(2)); + + // First identical call → allowed + let call_v1 = ToolCall::new("fetch_user".to_string(), json!({"id": 123})); + assert!(inspector.check_tool_call(call_v1.clone())); + + // Second identical call → still allowed (at limit) + assert!(inspector.check_tool_call(call_v1.clone())); + + // Third identical call → should be denied (exceeds limit) + assert!(!inspector.check_tool_call(call_v1.clone())); + + // Change parameters; this should reset the consecutive counter + let call_v2 = ToolCall::new("fetch_user".to_string(), json!({"id": 456})); + assert!(inspector.check_tool_call(call_v2.clone())); + + // Another identical call with new params → allowed (second in a row for this variant) + assert!(inspector.check_tool_call(call_v2.clone())); + + // One more identical call with new params → denied again + assert!(!inspector.check_tool_call(call_v2)); +}