()
| 1133 | |
| 1134 | #[tokio::test] |
| 1135 | async fn test_agent_hitl_partial_approval() { |
| 1136 | // Test: first tool approved, second rejected |
| 1137 | use crate::hitl::{ConfirmationManager, ConfirmationPolicy}; |
| 1138 | use tokio::sync::broadcast; |
| 1139 | |
| 1140 | let mock_client = Arc::new(MockLlmClient::new(vec![ |
| 1141 | // First response: two tool calls |
| 1142 | LlmResponse { |
| 1143 | message: Message { |
| 1144 | role: "assistant".to_string(), |
| 1145 | content: vec![ |
| 1146 | ContentBlock::ToolUse { |
| 1147 | id: "tool-1".to_string(), |
| 1148 | name: "bash".to_string(), |
| 1149 | input: serde_json::json!({"command": "echo safe"}), |
| 1150 | }, |
| 1151 | ContentBlock::ToolUse { |
| 1152 | id: "tool-2".to_string(), |
| 1153 | name: "bash".to_string(), |
| 1154 | input: serde_json::json!({"command": "rm -rf /"}), |
| 1155 | }, |
| 1156 | ], |
| 1157 | reasoning_content: None, |
| 1158 | }, |
| 1159 | usage: TokenUsage { |
| 1160 | prompt_tokens: 10, |
| 1161 | completion_tokens: 5, |
| 1162 | total_tokens: 15, |
| 1163 | cache_read_tokens: None, |
| 1164 | cache_write_tokens: None, |
| 1165 | }, |
| 1166 | stop_reason: Some("tool_use".to_string()), |
| 1167 | meta: None, |
| 1168 | }, |
| 1169 | MockLlmClient::text_response("First worked, second rejected."), |
| 1170 | ])); |
| 1171 | |
| 1172 | let tool_executor = Arc::new(ToolExecutor::new("/tmp".to_string())); |
| 1173 | |
| 1174 | let (event_tx, _event_rx) = broadcast::channel(100); |
| 1175 | let hitl_policy = ConfirmationPolicy { |
| 1176 | enabled: true, |
| 1177 | default_timeout_ms: 5000, |
| 1178 | ..Default::default() |
| 1179 | }; |
| 1180 | let confirmation_manager = Arc::new(ConfirmationManager::new(hitl_policy, event_tx)); |
| 1181 | |
| 1182 | let permission_policy = PermissionPolicy::new(); |
| 1183 | |
| 1184 | let config = AgentConfig { |
| 1185 | permission_checker: Some(Arc::new(permission_policy)), |
| 1186 | confirmation_manager: Some(confirmation_manager.clone()), |
| 1187 | ..Default::default() |
| 1188 | }; |
| 1189 | |
| 1190 | // Approve first, reject second |
| 1191 | let cm_clone = confirmation_manager.clone(); |
| 1192 | tokio::spawn(async move { |
nothing calls this directly
no test coverage detected