TUI 模式下的 HITL 审批处理器。 使用 Lanterna 弹窗显示审批请求。
| 16 | * <p>使用 Lanterna 弹窗显示审批请求。 |
| 17 | */ |
| 18 | public class TuiHitlHandler implements HitlHandler { |
| 19 | |
| 20 | private volatile boolean enabled = true; |
| 21 | |
| 22 | // 本次会话中已批准"全部放行"的集合 |
| 23 | private final Set<String> approvedAllByTool = ConcurrentHashMap.newKeySet(); |
| 24 | private final Set<String> approvedAllByServer = ConcurrentHashMap.newKeySet(); |
| 25 | |
| 26 | private final WindowBasedTextGUI gui; |
| 27 | |
| 28 | public TuiHitlHandler(WindowBasedTextGUI gui) { |
| 29 | this.gui = gui; |
| 30 | } |
| 31 | |
| 32 | @Override |
| 33 | public boolean isEnabled() { |
| 34 | return enabled; |
| 35 | } |
| 36 | |
| 37 | @Override |
| 38 | public void setEnabled(boolean enabled) { |
| 39 | this.enabled = enabled; |
| 40 | } |
| 41 | |
| 42 | @Override |
| 43 | public boolean isApprovedAllByTool(String toolName) { |
| 44 | return toolName != null && approvedAllByTool.contains(toolName); |
| 45 | } |
| 46 | |
| 47 | @Override |
| 48 | public boolean isApprovedAllByServer(String serverName) { |
| 49 | return serverName != null && approvedAllByServer.contains(serverName); |
| 50 | } |
| 51 | |
| 52 | @Override |
| 53 | public ApprovalResult requestApproval(ApprovalRequest request) { |
| 54 | if (!enabled) { |
| 55 | return ApprovalResult.approve(); |
| 56 | } |
| 57 | |
| 58 | String mcpServer = com.tcode.hitl.ApprovalPolicy.mcpServerName(request.toolName()); |
| 59 | boolean sensitivePerCall = request.sensitiveNotice() != null && !request.sensitiveNotice().isBlank(); |
| 60 | |
| 61 | // 检查是否已全部放行 |
| 62 | if (!sensitivePerCall && isApprovedAllByTool(request.toolName())) { |
| 63 | return ApprovalResult.approveAll(); |
| 64 | } |
| 65 | if (!sensitivePerCall && isApprovedAllByServer(mcpServer)) { |
| 66 | return ApprovalResult.approveAllByServer(); |
| 67 | } |
| 68 | |
| 69 | String title = "⚠️ HITL 审批请求"; |
| 70 | String content = request.toDisplayText() |
| 71 | + "\n\nYes: 批准本次 No: 拒绝 Cancel: 跳过"; |
| 72 | |
| 73 | MessageDialogBuilder dialog = new MessageDialogBuilder() |
| 74 | .setTitle(title) |
| 75 | .setText(content) |
nothing calls this directly
no outgoing calls
no test coverage detected