fix(approval): persist the real pendingId on guard audit rows

This commit is contained in:
matevip 2026-07-23 11:46:22 +08:00
parent 8174006b01
commit 49f7a74386
2 changed files with 19 additions and 18 deletions

View File

@ -1083,14 +1083,12 @@ public class ToolExecutionExecutor {
} }
List<AssistantMessage.ToolCall> remaining = allToolCalls.subList(currentIndex + 1, allToolCalls.size()); List<AssistantMessage.ToolCall> remaining = allToolCalls.subList(currentIndex + 1, allToolCalls.size());
String approvalResponse = ToolExecutionGuardHelper.handleToolApproval( ToolExecutionGuardHelper.ApprovalRequest approval = ToolExecutionGuardHelper.handleToolApproval(
toolCall, toolName, arguments, evaluation, toolCall, toolName, arguments, evaluation,
conversationId, agentId, requesterId, approvalService, streamTracker, conversationId, agentId, requesterId, approvalService, streamTracker,
events, remaining); events, remaining);
// Extract pendingId from response (format: "[APPROVAL_PENDING] tool=xxx awaiting user decision") toolGuardService.recordApprovalAudit(guardCtx, evaluation, approval.pendingId(), autoOutcome);
String pendingId = extractPendingId(approvalResponse); return GuardDecision.needsApproval(approval.response(), approval.pendingId());
toolGuardService.recordApprovalAudit(guardCtx, evaluation, pendingId, autoOutcome);
return GuardDecision.needsApproval(approvalResponse, pendingId);
} }
} else if (toolGuard != null) { } else if (toolGuard != null) {
ToolGuardResult guardResult = toolGuard.check(toolName, arguments); ToolGuardResult guardResult = toolGuard.check(toolName, arguments);
@ -1111,7 +1109,9 @@ public class ToolExecutionExecutor {
toolCall, toolName, arguments, guardResult, toolCall, toolName, arguments, guardResult,
conversationId, agentId, requesterId, approvalService, streamTracker, conversationId, agentId, requesterId, approvalService, streamTracker,
events, remaining); events, remaining);
return GuardDecision.needsApproval(approvalResponse, extractPendingId(approvalResponse)); // Legacy path never persisted a pendingId to carry here; the value
// is unused downstream (only the boolean awaitingApproval is read).
return GuardDecision.needsApproval(approvalResponse, null);
} }
} }
@ -1207,14 +1207,6 @@ public class ToolExecutionExecutor {
return "Tool execution failed: " + message; return "Tool execution failed: " + message;
} }
/**
* approval response 中提取 pendingIdbest-effort
*/
private String extractPendingId(String approvalResponse) {
// handleToolApproval 内部已经创建了 pending这里只做标记
return approvalResponse;
}
/** /**
* Issue #46 when a tool callback miss happens, check whether the * Issue #46 when a tool callback miss happens, check whether the
* unrecognized name actually matches an active skill. If it does, return * unrecognized name actually matches an active skill. If it does, return

View File

@ -27,7 +27,15 @@ public final class ToolExecutionGuardHelper {
* *
* @return 审批提示文本作为 tool response 返回给 LLM * @return 审批提示文本作为 tool response 返回给 LLM
*/ */
public static String handleToolApproval( /**
* Outcome of {@link #handleToolApproval}: the tool-response text handed back
* to the LLM plus the persisted pending-approval id. {@code pendingId} is
* null when the approval service is unavailable and the call degraded to a
* block-style message.
*/
public record ApprovalRequest(String response, String pendingId) {}
public static ApprovalRequest handleToolApproval(
AssistantMessage.ToolCall toolCall, String toolName, String arguments, AssistantMessage.ToolCall toolCall, String toolName, String arguments,
GuardEvaluation evaluation, String conversationId, String agentId, GuardEvaluation evaluation, String conversationId, String agentId,
String requesterId, String requesterId,
@ -39,8 +47,8 @@ public final class ToolExecutionGuardHelper {
log.warn("[GuardHelper] ApprovalService not available, falling back to BLOCK for tool={}", toolName); log.warn("[GuardHelper] ApprovalService not available, falling back to BLOCK for tool={}", toolName);
events.add(GraphEventPublisher.toolComplete(toolName, events.add(GraphEventPublisher.toolComplete(toolName,
evaluation.summary() != null ? evaluation.summary() : "需要审批", false)); evaluation.summary() != null ? evaluation.summary() : "需要审批", false));
return "[安全拦截] " + (evaluation.summary() != null ? evaluation.summary() : "需要审批") return new ApprovalRequest("[安全拦截] " + (evaluation.summary() != null ? evaluation.summary() : "需要审批")
+ "。审批服务不可用,请联系管理员。"; + "。审批服务不可用,请联系管理员。", null);
} }
String toolCallPayload = serializeToolCall(toolCall); String toolCallPayload = serializeToolCall(toolCall);
@ -78,7 +86,8 @@ public final class ToolExecutionGuardHelper {
log.info("[GuardHelper] Approval pending created: pendingId={}, tool={}, findings={}", log.info("[GuardHelper] Approval pending created: pendingId={}, tool={}, findings={}",
pendingId, toolName, evaluation.hasFindings() ? evaluation.findings().size() : 0); pendingId, toolName, evaluation.hasFindings() ? evaluation.findings().size() : 0);
return "[APPROVAL_PENDING] tool=" + toolName + " awaiting user decision"; return new ApprovalRequest(
"[APPROVAL_PENDING] tool=" + toolName + " awaiting user decision", pendingId);
} }
/** /**