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",