This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 6a461b2c8 fix(ai): tolerate alert rules without a metric in the rule 
list tool (#4571)
6a461b2c8 is described below

commit 6a461b2c831820f1f5388348a55b24e4263cb535
Author: Zhao Jianing <[email protected]>
AuthorDate: Sat Sep 26 18:24:27 2026 +0800

    fix(ai): tolerate alert rules without a metric in the rule list tool (#4571)
    
    fix(ai): tolerate alert rules without a metric in the rule list tool
    
    rmq.alert.rule.list declares metric as a required output field with
    minLength 1, but AlertService only validates name when a rule is
    created, so a metric-less rule is a legal stored state. AlertRuleListItem
    serializes with @JsonInclude(NON_NULL), so such a rule is emitted
    without a metric key and ToolValidationFilter rejects the whole
    response with "required property 'metric' not found" — one metric-less
    rule breaks the entire tool call.
    
    Align the schema with the service contract the same way acl.yaml treats
    gmtCreate: drop metric from the required list and declare it
    [string, 'null']. Lock it in with a null-metric sample in the
    ToolOutputSchemaContractTest sweep.
    
    Signed-off-by: zjncs <[email protected]>
---
 rmqctl/internal/catalog/catalog_gen.go                              | 2 +-
 server/src/main/resources/tool-catalog/tools/alert.yaml             | 6 +++---
 .../studio/ops/ai/tool/service/ToolOutputSchemaContractTest.java    | 6 +++++-
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/rmqctl/internal/catalog/catalog_gen.go 
b/rmqctl/internal/catalog/catalog_gen.go
index 47ffa019c..78319554d 100644
--- a/rmqctl/internal/catalog/catalog_gen.go
+++ b/rmqctl/internal/catalog/catalog_gen.go
@@ -21,7 +21,7 @@ package catalog
 var defaultDocument = Document{
        Version:              "2.0.0",
        MinimumClientVersion: "2.0.0",
-       Digest:               
"30a907ada71734e87305982bcf29a3ff7c6f3ae050a2211f06e87c11b0424e2d",
+       Digest:               
"b0c1321d5d026c78d0cd51a142bef55f20e3370e5609b79cdcf85c933e208f91",
        Tools: []Tool{
                {
                        Name:                 "rmq.acl.list",
diff --git a/server/src/main/resources/tool-catalog/tools/alert.yaml 
b/server/src/main/resources/tool-catalog/tools/alert.yaml
index 9c6e5d63b..bb9edd8df 100644
--- a/server/src/main/resources/tool-catalog/tools/alert.yaml
+++ b/server/src/main/resources/tool-catalog/tools/alert.yaml
@@ -31,7 +31,6 @@ tools:
             required:
               - id
               - name
-              - metric
               - threshold
               - channels
               - enabled
@@ -43,8 +42,9 @@ tools:
                 type: string
                 minLength: 1
               metric:
-                type: string
-                minLength: 1
+                type:
+                  - string
+                  - 'null'
               operator:
                 type: string
               threshold:
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/service/ToolOutputSchemaContractTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/service/ToolOutputSchemaContractTest.java
index d72960cc6..e6aa8f80b 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/service/ToolOutputSchemaContractTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/service/ToolOutputSchemaContractTest.java
@@ -137,9 +137,13 @@ class ToolOutputSchemaContractTest {
         samples.put("rmq.user.create", List.of(planned(), executed(user)));
         samples.put("rmq.user.delete", List.of(planned(), executedVoid()));
 
+        // metric is optional at the service layer (AlertService only 
validates name),
+        // so a metric-less rule must still validate against the output schema
         samples.put("rmq.alert.rule.list", List.of(new ListOutput<>(List.of(
                 new AlertRuleListItem(1L, "consumer-lag", 
"consumer.lag.total", ">",
-                        1000.0, "count", "5m", List.of("dingtalk"), true, "lag 
alert")))));
+                        1000.0, "count", "5m", List.of("dingtalk"), true, "lag 
alert"),
+                new AlertRuleListItem(2L, "draft-rule", null, null,
+                        0.0, null, null, List.of(), false, null)))));
 
         samples.put("rmq.audit.list", List.of(new PageOutput<>(1, 20, 1L, 
List.of(
                 new AuditItem(1L, "2026-08-22T08:00:00", "admin", 
"CREATE_TOPIC", "TOPIC",

Reply via email to