From 1b93474a67aa2323d20630b1bb026713b2bad009 Mon Sep 17 00:00:00 2001
From: Junjie <fallin.jie@qq.com>
Date: 星期三, 29 四月 2026 16:59:32 +0800
Subject: [PATCH] #Agent自动调参

---
 src/main/java/com/zy/ai/mcp/tool/AutoTuneMcpTools.java |   88 ++++++++++++++++++++++++++++++++++++-------
 1 files changed, 73 insertions(+), 15 deletions(-)

diff --git a/src/main/java/com/zy/ai/mcp/tool/AutoTuneMcpTools.java b/src/main/java/com/zy/ai/mcp/tool/AutoTuneMcpTools.java
index 1167739..ea5bc1c 100644
--- a/src/main/java/com/zy/ai/mcp/tool/AutoTuneMcpTools.java
+++ b/src/main/java/com/zy/ai/mcp/tool/AutoTuneMcpTools.java
@@ -15,6 +15,7 @@
 import com.zy.ai.service.AiAutoTuneMcpCallService;
 import com.zy.ai.service.AutoTuneApplyService;
 import com.zy.ai.service.AutoTuneSnapshotService;
+import com.zy.ai.utils.AutoTuneWriteBehaviorUtils;
 import lombok.RequiredArgsConstructor;
 import org.springframework.ai.tool.annotation.Tool;
 import org.springframework.ai.tool.annotation.ToolParam;
@@ -83,10 +84,6 @@
         if (dryRun == null) {
             throw new IllegalArgumentException("dryRun is required. Use dryRun=true first to create a preview token.");
         }
-        String fingerprint = buildChangeFingerprint(changes);
-        if (Boolean.FALSE.equals(dryRun)) {
-            requireMatchingDryRunToken(dryRunToken, fingerprint);
-        }
 
         AutoTuneApplyRequest request = new AutoTuneApplyRequest();
         request.setReason(reason);
@@ -94,8 +91,14 @@
         request.setTriggerType(triggerType);
         request.setDryRun(dryRun);
         request.setChanges(changes);
+
+        String fingerprint = buildChangeFingerprint(changes);
+        if (Boolean.FALSE.equals(dryRun)) {
+            requireMatchingDryRunToken(dryRunToken, fingerprint);
+        }
+
         AutoTuneApplyResult result = autoTuneApplyService.apply(request);
-        if (Boolean.TRUE.equals(dryRun) && isSuccessful(result)) {
+        if (Boolean.TRUE.equals(dryRun) && hasApplicableDryRunChanges(result)) {
             result.setDryRunToken(createDryRunToken(fingerprint));
         }
         return result;
@@ -119,9 +122,13 @@
         item.put("rejectCount", job.getRejectCount());
         item.put("errorMessage", job.getErrorMessage());
         List<AiAutoTuneMcpCall> mcpCalls = listMcpCalls(job.getId());
+        List<Map<String, Object>> mcpCallSummaries = toMcpCallSummaries(mcpCalls);
+        List<Map<String, Object>> changeSummaries = listChangeSummaries(job, mcpCalls);
+        AutoTuneWriteBehaviorUtils.addWriteBehavior(item,
+                AutoTuneWriteBehaviorUtils.resolveJobWriteBehavior(job, mcpCallSummaries, changeSummaries));
         item.put("mcpCallCount", mcpCalls.size());
-        item.put("mcpCalls", toMcpCallSummaries(mcpCalls));
-        item.put("changes", listChangeSummaries(mcpCalls));
+        item.put("mcpCalls", mcpCallSummaries);
+        item.put("changes", changeSummaries);
         return item;
     }
 
@@ -157,6 +164,8 @@
         item.put("successCount", mcpCall.getSuccessCount());
         item.put("rejectCount", mcpCall.getRejectCount());
         item.put("errorMessage", mcpCall.getErrorMessage());
+        AutoTuneWriteBehaviorUtils.addWriteBehavior(item,
+                AutoTuneWriteBehaviorUtils.resolveMcpWriteBehavior(mcpCall));
         return item;
     }
 
@@ -167,8 +176,9 @@
         return value == 1;
     }
 
-    private List<Map<String, Object>> listChangeSummaries(List<AiAutoTuneMcpCall> mcpCalls) {
-        List<Long> applyJobIds = collectApplyJobIds(mcpCalls);
+    private List<Map<String, Object>> listChangeSummaries(AiAutoTuneJob job, List<AiAutoTuneMcpCall> mcpCalls) {
+        Map<Long, String> ownerTriggerTypes = collectChangeOwnerTriggerTypes(job, mcpCalls);
+        List<Long> applyJobIds = new ArrayList<>(ownerTriggerTypes.keySet());
         if (applyJobIds.isEmpty()) {
             return new ArrayList<>();
         }
@@ -182,27 +192,40 @@
 
         List<Map<String, Object>> result = new ArrayList<>();
         for (AiAutoTuneChange change : changes) {
-            result.add(toChangeSummary(change));
+            result.add(toChangeSummary(change, ownerTriggerTypes.get(change.getJobId())));
         }
         return result;
     }
 
-    private List<Long> collectApplyJobIds(List<AiAutoTuneMcpCall> mcpCalls) {
-        List<Long> result = new ArrayList<>();
+    private Map<Long, String> collectChangeOwnerTriggerTypes(AiAutoTuneJob job, List<AiAutoTuneMcpCall> mcpCalls) {
+        LinkedHashMap<Long, String> result = new LinkedHashMap<>();
+        if (job != null && job.getId() != null) {
+            result.put(job.getId(), job.getTriggerType());
+        }
         if (mcpCalls == null || mcpCalls.isEmpty()) {
             return result;
         }
         for (AiAutoTuneMcpCall mcpCall : mcpCalls) {
             Long applyJobId = mcpCall.getApplyJobId();
-            if (applyJobId != null && !result.contains(applyJobId)) {
-                result.add(applyJobId);
+            if (applyJobId == null || result.containsKey(applyJobId)) {
+                continue;
             }
+            result.put(applyJobId, resolveMcpApplyJobTriggerType(mcpCall));
         }
         return result;
     }
 
-    private Map<String, Object> toChangeSummary(AiAutoTuneChange change) {
+    private String resolveMcpApplyJobTriggerType(AiAutoTuneMcpCall mcpCall) {
+        if (mcpCall == null || mcpCall.getToolName() == null) {
+            return null;
+        }
+        String toolName = mcpCall.getToolName().toLowerCase(Locale.ROOT);
+        return toolName.contains("revert_last_auto_tune_job") || toolName.contains("rollback") ? "rollback" : null;
+    }
+
+    private Map<String, Object> toChangeSummary(AiAutoTuneChange change, String ownerTriggerType) {
         LinkedHashMap<String, Object> item = new LinkedHashMap<>();
+        item.put("jobId", change.getJobId());
         item.put("targetType", change.getTargetType());
         item.put("targetId", change.getTargetId());
         item.put("targetKey", change.getTargetKey());
@@ -213,6 +236,8 @@
         item.put("rejectReason", change.getRejectReason());
         item.put("cooldownExpireTime", change.getCooldownExpireTime());
         item.put("createTime", change.getCreateTime());
+        AutoTuneWriteBehaviorUtils.addWriteBehavior(item,
+                AutoTuneWriteBehaviorUtils.resolveChangeWriteBehavior(change, ownerTriggerType));
         return item;
     }
 
@@ -260,6 +285,18 @@
         return result != null && Boolean.TRUE.equals(result.getSuccess());
     }
 
+    private boolean hasApplicableDryRunChanges(AutoTuneApplyResult result) {
+        if (!isSuccessful(result) || result.getChanges() == null || result.getChanges().isEmpty()) {
+            return false;
+        }
+        for (AiAutoTuneChange change : result.getChanges()) {
+            if (change != null && "dry_run".equals(normalizeLower(change.getResultStatus()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private String buildChangeFingerprint(List<AutoTuneChangeCommand> changes) {
         List<Map<String, String>> normalizedChanges = new ArrayList<>();
         if (changes != null) {
@@ -267,6 +304,7 @@
                 normalizedChanges.add(toNormalizedChange(change));
             }
         }
+        validateUniqueChangeTargets(normalizedChanges);
         normalizedChanges.sort(Comparator
                 .comparing((Map<String, String> item) -> item.get("targetType"))
                 .thenComparing(item -> item.get("targetId"))
@@ -275,6 +313,26 @@
         return JSON.toJSONString(normalizedChanges);
     }
 
+    private void validateUniqueChangeTargets(List<Map<String, String>> normalizedChanges) {
+        Map<String, Map<String, String>> uniqueTargets = new LinkedHashMap<>();
+        for (Map<String, String> change : normalizedChanges) {
+            String targetSignature = buildTargetSignature(change);
+            if (uniqueTargets.containsKey(targetSignature)) {
+                throw new IllegalArgumentException("Duplicate auto-tune change target in same request: "
+                        + "targetType=" + change.get("targetType")
+                        + ", targetId=" + change.get("targetId")
+                        + ", targetKey=" + change.get("targetKey"));
+            }
+            uniqueTargets.put(targetSignature, change);
+        }
+    }
+
+    private String buildTargetSignature(Map<String, String> change) {
+        return change.get("targetType") + "\n"
+                + change.get("targetId") + "\n"
+                + change.get("targetKey");
+    }
+
     private Map<String, String> toNormalizedChange(AutoTuneChangeCommand change) {
         LinkedHashMap<String, String> item = new LinkedHashMap<>();
         String targetType = normalizeLower(change == null ? null : change.getTargetType());

--
Gitblit v1.9.1