mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-31 16:49:34 +00:00
fix: destructive actions from ambiguous user prompts (#782)
* fix: destructive actions from ambiguous user prompts * review fixes * review fixes
This commit is contained in:
@@ -1263,6 +1263,96 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_always_approval_requirement_bypasses_session_auto_approve() {
|
||||
// Regression test: even if tool is auto-approved in session,
|
||||
// ApprovalRequirement::Always must still trigger approval.
|
||||
use crate::tools::ApprovalRequirement;
|
||||
|
||||
let mut session = Session::new("user-1");
|
||||
let tool_name = "tool_remove";
|
||||
|
||||
// Manually auto-approve tool_remove in this session
|
||||
session.auto_approve_tool(tool_name);
|
||||
assert!(
|
||||
session.is_tool_auto_approved(tool_name),
|
||||
"tool should be auto-approved"
|
||||
);
|
||||
|
||||
// However, ApprovalRequirement::Always should always require approval
|
||||
// This is verified by the dispatcher logic: Always => true (ignores session state)
|
||||
let always_req = ApprovalRequirement::Always;
|
||||
let requires_approval = match always_req {
|
||||
ApprovalRequirement::Never => false,
|
||||
ApprovalRequirement::UnlessAutoApproved => !session.is_tool_auto_approved(tool_name),
|
||||
ApprovalRequirement::Always => true,
|
||||
};
|
||||
|
||||
assert!(
|
||||
requires_approval,
|
||||
"ApprovalRequirement::Always must require approval even when tool is auto-approved"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_always_approval_requirement_vs_unless_auto_approved() {
|
||||
// Verify the two requirements behave differently
|
||||
use crate::tools::ApprovalRequirement;
|
||||
|
||||
let mut session = Session::new("user-2");
|
||||
let tool_name = "http";
|
||||
|
||||
// Scenario 1: Tool is auto-approved
|
||||
session.auto_approve_tool(tool_name);
|
||||
|
||||
// UnlessAutoApproved → doesn't require approval if auto-approved
|
||||
let unless_req = ApprovalRequirement::UnlessAutoApproved;
|
||||
let unless_needs = match unless_req {
|
||||
ApprovalRequirement::Never => false,
|
||||
ApprovalRequirement::UnlessAutoApproved => !session.is_tool_auto_approved(tool_name),
|
||||
ApprovalRequirement::Always => true,
|
||||
};
|
||||
assert!(
|
||||
!unless_needs,
|
||||
"UnlessAutoApproved should not need approval when auto-approved"
|
||||
);
|
||||
|
||||
// Always → always requires approval
|
||||
let always_req = ApprovalRequirement::Always;
|
||||
let always_needs = match always_req {
|
||||
ApprovalRequirement::Never => false,
|
||||
ApprovalRequirement::UnlessAutoApproved => !session.is_tool_auto_approved(tool_name),
|
||||
ApprovalRequirement::Always => true,
|
||||
};
|
||||
assert!(
|
||||
always_needs,
|
||||
"Always must always require approval, even when auto-approved"
|
||||
);
|
||||
|
||||
// Scenario 2: Tool is NOT auto-approved
|
||||
let new_tool = "new_tool";
|
||||
assert!(!session.is_tool_auto_approved(new_tool));
|
||||
|
||||
// UnlessAutoApproved → requires approval
|
||||
let unless_needs = match unless_req {
|
||||
ApprovalRequirement::Never => false,
|
||||
ApprovalRequirement::UnlessAutoApproved => !session.is_tool_auto_approved(new_tool),
|
||||
ApprovalRequirement::Always => true,
|
||||
};
|
||||
assert!(
|
||||
unless_needs,
|
||||
"UnlessAutoApproved should need approval when not auto-approved"
|
||||
);
|
||||
|
||||
// Always → always requires approval
|
||||
let always_needs = match always_req {
|
||||
ApprovalRequirement::Never => false,
|
||||
ApprovalRequirement::UnlessAutoApproved => !session.is_tool_auto_approved(new_tool),
|
||||
ApprovalRequirement::Always => true,
|
||||
};
|
||||
assert!(always_needs, "Always must always require approval");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pending_approval_serialization_backcompat_without_deferred_calls() {
|
||||
// PendingApproval from before the deferred_tool_calls field was added
|
||||
|
||||
Reference in New Issue
Block a user