From 63b01db83d9aad8a15276b4236a9a22e4aeef065 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期二, 05 五月 2026 12:30:59 +0800
Subject: [PATCH] # Agent数据分析V3.0.1.7

---
 src/main/java/com/zy/ai/service/impl/AutoTuneCoordinatorServiceImpl.java |  261 +++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 227 insertions(+), 34 deletions(-)

diff --git a/src/main/java/com/zy/ai/service/impl/AutoTuneCoordinatorServiceImpl.java b/src/main/java/com/zy/ai/service/impl/AutoTuneCoordinatorServiceImpl.java
index 808895a..6e3148b 100644
--- a/src/main/java/com/zy/ai/service/impl/AutoTuneCoordinatorServiceImpl.java
+++ b/src/main/java/com/zy/ai/service/impl/AutoTuneCoordinatorServiceImpl.java
@@ -2,11 +2,16 @@
 
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.zy.ai.domain.autotune.AutoTuneControlModeSnapshot;
 import com.zy.ai.domain.autotune.AutoTuneJobStatus;
 import com.zy.ai.domain.autotune.AutoTuneTriggerType;
+import com.zy.ai.entity.AiAutoTuneMcpCall;
 import com.zy.ai.entity.AiAutoTuneJob;
+import com.zy.ai.enums.AiPromptScene;
 import com.zy.ai.service.AiAutoTuneJobService;
+import com.zy.ai.service.AiAutoTuneMcpCallService;
 import com.zy.ai.service.AutoTuneAgentService;
+import com.zy.ai.service.AutoTuneControlModeService;
 import com.zy.ai.service.AutoTuneCoordinatorService;
 import com.zy.asrs.entity.WrkMast;
 import com.zy.asrs.service.WrkMastService;
@@ -20,6 +25,7 @@
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.LinkedHashMap;
@@ -32,9 +38,7 @@
 @RequiredArgsConstructor
 public class AutoTuneCoordinatorServiceImpl implements AutoTuneCoordinatorService {
 
-    private static final String CONFIG_ENABLED = "aiAutoTuneEnabled";
     private static final String CONFIG_INTERVAL_MINUTES = "aiAutoTuneIntervalMinutes";
-    private static final String DEFAULT_ENABLED = "N";
     private static final int DEFAULT_INTERVAL_MINUTES = 10;
     private static final int MIN_INTERVAL_MINUTES = 5;
     private static final int MAX_INTERVAL_MINUTES = 60;
@@ -50,8 +54,10 @@
     );
 
     private final ConfigService configService;
+    private final AutoTuneControlModeService autoTuneControlModeService;
     private final WrkMastService wrkMastService;
     private final AiAutoTuneJobService aiAutoTuneJobService;
+    private final AiAutoTuneMcpCallService aiAutoTuneMcpCallService;
     private final AutoTuneAgentService autoTuneAgentService;
     private final RedisUtil redisUtil;
     private final OperateLogService operateLogService;
@@ -75,6 +81,15 @@
             return AutoTuneCoordinatorResult.skipped("interval_not_reached");
         }
 
+        return runAgentWithLock(AutoTuneTriggerType.AUTO.getCode(), intervalMinutes, true);
+    }
+
+    @Override
+    public AutoTuneCoordinatorResult runManualAutoTune() {
+        return runAgentWithLock(AutoTuneTriggerType.MANUAL.getCode(), null, false);
+    }
+
+    private AutoTuneCoordinatorResult runAgentWithLock(String triggerType, Integer intervalMinutes, boolean writeGuard) {
         String lockKey = RedisKeyType.AI_AUTO_TUNE_RUNNING_LOCK.key;
         String lockToken = UUID.randomUUID().toString();
         if (!redisUtil.trySetStringIfAbsent(lockKey, lockToken, RUNNING_LOCK_SECONDS)) {
@@ -82,15 +97,20 @@
         }
 
         AutoTuneAgentService.AutoTuneAgentResult agentResult = null;
+        Date startTime = new Date();
         try {
-            agentResult = autoTuneAgentService.runAutoTune(AutoTuneTriggerType.AUTO.getCode());
-            writeOperateLog(agentResult);
-            markNoChangeGuardIfNeeded(latestSuccessfulJob, agentResult, intervalMinutes);
+            if (writeGuard && intervalMinutes != null) {
+                safeMarkLastTriggerGuard(intervalMinutes);
+            }
+            agentResult = autoTuneAgentService.runAutoTune(triggerType);
+            safeWriteOperateLog(agentResult);
+            safeWriteAgentRunAudit(triggerType, startTime, agentResult);
             return AutoTuneCoordinatorResult.triggered(agentResult);
         } catch (Exception exception) {
             log.error("Auto tune coordinator failed to run agent", exception);
-            agentResult = failedAgentResult(exception);
-            writeOperateLog(agentResult);
+            agentResult = failedAgentResult(triggerType, exception);
+            safeWriteOperateLog(agentResult);
+            safeWriteAgentRunAudit(triggerType, startTime, agentResult);
             return AutoTuneCoordinatorResult.triggered(agentResult);
         } finally {
             redisUtil.compareAndDelete(lockKey, lockToken);
@@ -98,14 +118,8 @@
     }
 
     private boolean isEnabled() {
-        String enabled = configService.getConfigValue(CONFIG_ENABLED, DEFAULT_ENABLED);
-        if (enabled == null) {
-            return false;
-        }
-        String normalized = enabled.trim();
-        return "Y".equalsIgnoreCase(normalized)
-                || "true".equalsIgnoreCase(normalized)
-                || "1".equals(normalized);
+        AutoTuneControlModeSnapshot controlMode = autoTuneControlModeService.currentMode();
+        return controlMode != null && Boolean.TRUE.equals(controlMode.getEnabled());
     }
 
     private int resolveIntervalMinutes() {
@@ -159,32 +173,25 @@
         return System.currentTimeMillis() - latestFinishTime.getTime() >= intervalMillis;
     }
 
-    private void markNoChangeGuardIfNeeded(AiAutoTuneJob beforeJob,
-                                           AutoTuneAgentService.AutoTuneAgentResult agentResult,
-                                           int intervalMinutes) {
-        if (agentResult == null || !Boolean.TRUE.equals(agentResult.getSuccess())) {
-            return;
+    private void safeMarkLastTriggerGuard(int intervalMinutes) {
+        try {
+            markLastTriggerGuard(intervalMinutes);
+        } catch (Exception exception) {
+            log.warn("Auto tune coordinator failed to write last trigger guard", exception);
         }
-        AiAutoTuneJob afterJob = latestSuccessfulAutoJob();
-        if (!isSameJob(beforeJob, afterJob)) {
-            return;
-        }
+    }
+
+    private void markLastTriggerGuard(int intervalMinutes) {
         long expireSeconds = intervalMinutes * 60L;
         redisUtil.set(RedisKeyType.AI_AUTO_TUNE_LAST_TRIGGER_GUARD.key,
                 String.valueOf(System.currentTimeMillis()), expireSeconds);
     }
 
-    private boolean isSameJob(AiAutoTuneJob beforeJob, AiAutoTuneJob afterJob) {
-        if (beforeJob == null || afterJob == null) {
-            return beforeJob == afterJob;
-        }
-        return beforeJob.getId() != null && beforeJob.getId().equals(afterJob.getId());
-    }
-
-    private AutoTuneAgentService.AutoTuneAgentResult failedAgentResult(Exception exception) {
+    private AutoTuneAgentService.AutoTuneAgentResult failedAgentResult(String triggerType, Exception exception) {
+        AutoTuneControlModeSnapshot controlMode = autoTuneControlModeService.currentMode();
         AutoTuneAgentService.AutoTuneAgentResult result = new AutoTuneAgentService.AutoTuneAgentResult();
         result.setSuccess(false);
-        result.setTriggerType(AutoTuneTriggerType.AUTO.getCode());
+        result.setTriggerType(triggerType);
         result.setSummary("鑷姩璋冨弬鍚庡彴浠诲姟鎵ц寮傚父: " + exception.getMessage());
         result.setToolCallCount(0);
         result.setLlmCallCount(0);
@@ -192,7 +199,175 @@
         result.setCompletionTokens(0L);
         result.setTotalTokens(0L);
         result.setMaxRoundsReached(false);
+        result.setAnalysisOnly(controlMode.getAnalysisOnly());
+        result.setAllowApply(controlMode.getAllowApply());
+        result.setExecutionMode(controlMode.getModeCode());
+        result.setActualApplyCalled(false);
+        result.setRollbackCalled(false);
+        result.setSuccessCount(0);
+        result.setRejectCount(0);
+        result.setMcpCalls(new ArrayList<>());
         return result;
+    }
+
+    private void safeWriteAgentRunAudit(String triggerType,
+                                        Date startTime,
+                                        AutoTuneAgentService.AutoTuneAgentResult agentResult) {
+        try {
+            writeAgentRunAudit(triggerType, startTime, agentResult);
+        } catch (Exception exception) {
+            log.warn("Auto tune coordinator failed to write agent run audit", exception);
+        }
+    }
+
+    private void writeAgentRunAudit(String triggerType,
+                                    Date startTime,
+                                    AutoTuneAgentService.AutoTuneAgentResult agentResult) {
+        if (agentResult == null) {
+            return;
+        }
+        Date finishTime = new Date();
+        Integer intervalMinutes = resolveIntervalMinutes();
+        AiAutoTuneJob job = new AiAutoTuneJob();
+        job.setTriggerType(AutoTuneTriggerType.normalize(triggerType));
+        job.setStatus(resolveAuditStatus(agentResult));
+        job.setStartTime(startTime == null ? finishTime : startTime);
+        job.setFinishTime(finishTime);
+        job.setHasActiveTasks(resolveHasActiveTasksForAudit());
+        job.setPromptSceneCode(AiPromptScene.AUTO_TUNE_DISPATCH.getCode());
+        job.setSummary(agentResult.getSummary());
+        job.setIntervalBefore(intervalMinutes);
+        job.setIntervalAfter(intervalMinutes);
+        job.setSuccessCount(safeCount(agentResult.getSuccessCount()));
+        job.setRejectCount(safeCount(agentResult.getRejectCount()));
+        if (isErrorAuditStatus(job.getStatus())) {
+            job.setErrorMessage(agentResult.getSummary());
+        }
+        job.setLlmCallCount(agentResult.getLlmCallCount() == null ? 0 : agentResult.getLlmCallCount());
+        job.setPromptTokens(toSafeInteger(agentResult.getPromptTokens()));
+        job.setCompletionTokens(toSafeInteger(agentResult.getCompletionTokens()));
+        job.setTotalTokens(toSafeInteger(agentResult.getTotalTokens()));
+        job.setCreateTime(job.getStartTime());
+        if (!aiAutoTuneJobService.save(job)) {
+            log.warn("Auto tune coordinator failed to save agent run audit");
+            return;
+        }
+        safeWriteMcpCallAudit(job.getId(), agentResult);
+    }
+
+    private void safeWriteMcpCallAudit(Long agentJobId, AutoTuneAgentService.AutoTuneAgentResult agentResult) {
+        try {
+            writeMcpCallAudit(agentJobId, agentResult);
+        } catch (Exception exception) {
+            log.warn("Auto tune coordinator failed to write MCP call audit", exception);
+        }
+    }
+
+    private void writeMcpCallAudit(Long agentJobId, AutoTuneAgentService.AutoTuneAgentResult agentResult) {
+        if (agentJobId == null || agentResult == null || agentResult.getMcpCalls() == null
+                || agentResult.getMcpCalls().isEmpty()) {
+            return;
+        }
+        List<AiAutoTuneMcpCall> mcpCalls = new ArrayList<>();
+        Date createTime = new Date();
+        for (AutoTuneAgentService.McpCallResult callResult : agentResult.getMcpCalls()) {
+            mcpCalls.add(toMcpCallEntity(agentJobId, callResult, createTime));
+        }
+        if (!aiAutoTuneMcpCallService.saveBatch(mcpCalls)) {
+            log.warn("Auto tune coordinator failed to save MCP call audit");
+        }
+    }
+
+    private AiAutoTuneMcpCall toMcpCallEntity(Long agentJobId,
+                                              AutoTuneAgentService.McpCallResult callResult,
+                                              Date createTime) {
+        AiAutoTuneMcpCall mcpCall = new AiAutoTuneMcpCall();
+        mcpCall.setAgentJobId(agentJobId);
+        mcpCall.setCallSeq(callResult.getCallSeq());
+        mcpCall.setToolName(callResult.getToolName());
+        mcpCall.setStatus(callResult.getStatus());
+        mcpCall.setDryRun(toTinyInt(callResult.getDryRun()));
+        mcpCall.setApplyJobId(callResult.getApplyJobId());
+        mcpCall.setSuccessCount(safeCount(callResult.getSuccessCount()));
+        mcpCall.setRejectCount(safeCount(callResult.getRejectCount()));
+        mcpCall.setDurationMs(callResult.getDurationMs());
+        mcpCall.setRequestJson(callResult.getRequestJson());
+        mcpCall.setResponseJson(callResult.getResponseJson());
+        mcpCall.setErrorMessage(callResult.getErrorMessage());
+        mcpCall.setCreateTime(createTime);
+        return mcpCall;
+    }
+
+    private Integer toTinyInt(Boolean value) {
+        if (value == null) {
+            return null;
+        }
+        return value ? 1 : 0;
+    }
+
+    private String resolveAuditStatus(AutoTuneAgentService.AutoTuneAgentResult agentResult) {
+        int successCount = safeCount(agentResult.getSuccessCount());
+        int rejectCount = safeCount(agentResult.getRejectCount());
+        if (!Boolean.TRUE.equals(agentResult.getSuccess())) {
+            if (successCount > 0 && rejectCount > 0) {
+                return AutoTuneJobStatus.PARTIAL_SUCCESS.getCode();
+            }
+            if (rejectCount > 0) {
+                return AutoTuneJobStatus.REJECTED.getCode();
+            }
+            return AutoTuneJobStatus.FAILED.getCode();
+        }
+        if (successCount > 0 && rejectCount > 0) {
+            return AutoTuneJobStatus.PARTIAL_SUCCESS.getCode();
+        }
+        if (rejectCount > 0) {
+            return AutoTuneJobStatus.REJECTED.getCode();
+        }
+        if (Boolean.TRUE.equals(agentResult.getActualApplyCalled())
+                || Boolean.TRUE.equals(agentResult.getRollbackCalled())) {
+            return AutoTuneJobStatus.SUCCESS.getCode();
+        }
+        return AutoTuneJobStatus.NO_CHANGE.getCode();
+    }
+
+    private boolean isErrorAuditStatus(String status) {
+        return AutoTuneJobStatus.FAILED.getCode().equals(status)
+                || AutoTuneJobStatus.REJECTED.getCode().equals(status)
+                || AutoTuneJobStatus.PARTIAL_SUCCESS.getCode().equals(status);
+    }
+
+    private int safeCount(Integer value) {
+        return value == null ? 0 : value;
+    }
+
+    private int resolveHasActiveTasksForAudit() {
+        try {
+            return hasActiveTasks() ? 1 : 0;
+        } catch (RuntimeException exception) {
+            log.warn("Auto tune coordinator failed to query active tasks for audit", exception);
+            return 0;
+        }
+    }
+
+    private Integer toSafeInteger(Long value) {
+        if (value == null) {
+            return 0;
+        }
+        if (value > Integer.MAX_VALUE) {
+            return Integer.MAX_VALUE;
+        }
+        if (value < Integer.MIN_VALUE) {
+            return Integer.MIN_VALUE;
+        }
+        return value.intValue();
+    }
+
+    private void safeWriteOperateLog(AutoTuneAgentService.AutoTuneAgentResult agentResult) {
+        try {
+            writeOperateLog(agentResult);
+        } catch (Exception exception) {
+            log.warn("Auto tune coordinator failed to write operate log", exception);
+        }
     }
 
     private void writeOperateLog(AutoTuneAgentService.AutoTuneAgentResult agentResult) {
@@ -200,7 +375,7 @@
             return;
         }
         OperateLog operateLog = new OperateLog();
-        operateLog.setAction("ai_auto_tune_background_scheduler");
+        operateLog.setAction(resolveOperateLogAction(agentResult));
         operateLog.setUserId(SYSTEM_USER_ID);
         operateLog.setIp("system");
         operateLog.setRequest(JSON.toJSONString(buildRequestSummary(agentResult)));
@@ -209,9 +384,19 @@
         operateLogService.save(operateLog);
     }
 
+    private String resolveOperateLogAction(AutoTuneAgentService.AutoTuneAgentResult agentResult) {
+        if (agentResult != null && AutoTuneTriggerType.MANUAL.getCode().equals(agentResult.getTriggerType())) {
+            return "ai_auto_tune_manual_trigger";
+        }
+        return "ai_auto_tune_background_scheduler";
+    }
+
     private Map<String, Object> buildRequestSummary(AutoTuneAgentService.AutoTuneAgentResult agentResult) {
         Map<String, Object> request = new LinkedHashMap<>();
         request.put("trigger", agentResult.getTriggerType());
+        request.put("analysisOnly", agentResult.getAnalysisOnly());
+        request.put("allowApply", agentResult.getAllowApply());
+        request.put("executionMode", agentResult.getExecutionMode());
         return request;
     }
 
@@ -219,12 +404,20 @@
         Map<String, Object> response = new LinkedHashMap<>();
         response.put("success", agentResult.getSuccess());
         response.put("summary", agentResult.getSummary());
+        response.put("analysisOnly", agentResult.getAnalysisOnly());
+        response.put("allowApply", agentResult.getAllowApply());
+        response.put("executionMode", agentResult.getExecutionMode());
         response.put("toolCallCount", agentResult.getToolCallCount());
         response.put("llmCallCount", agentResult.getLlmCallCount());
         response.put("promptTokens", agentResult.getPromptTokens());
         response.put("completionTokens", agentResult.getCompletionTokens());
         response.put("totalTokens", agentResult.getTotalTokens());
         response.put("maxRoundsReached", agentResult.getMaxRoundsReached());
+        response.put("actualApplyCalled", agentResult.getActualApplyCalled());
+        response.put("rollbackCalled", agentResult.getRollbackCalled());
+        response.put("successCount", agentResult.getSuccessCount());
+        response.put("rejectCount", agentResult.getRejectCount());
+        response.put("mcpCallCount", agentResult.getMcpCalls() == null ? 0 : agentResult.getMcpCalls().size());
         return response;
     }
 }

--
Gitblit v1.9.1