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 22aee3385 feat(ai): add LiteTopic list, session and quota read tools
(#4771)
22aee3385 is described below
commit 22aee3385dff80016f0d304a4a4fde60661b8163
Author: pilichoumao <[email protected]>
AuthorDate: Sat Sep 26 18:31:34 2026 +0800
feat(ai): add LiteTopic list, session and quota read tools (#4771)
feat(ai): add LiteTopic list, session and quota read tools
LiteTopic is a headline 5.0 capability and the Studio pages already
serve pattern aggregates, session views and quota watermarks from the
broker lite admin API (#4220), but the tool catalog had no LiteTopic
entry: an LLM or CLI operator diagnosing session-scale topics could
not reach any of it, although AI-01 coverage requires the A-K
capabilities to exist as tools.
Add three L1 read-only tools over the existing LiteTopicService:
rmq.litetopic.list (pattern aggregates with optional pattern prefix
and namespace filters), rmq.litetopic.session (one session with its
per-topic entries) and rmq.litetopic.quota (quota watermark). Outputs
map the existing VOs without inventing data: statistics a broker
cannot report stay absent instead of being zero-filled, and a cluster
without lite support surfaces the provider's 501 unchanged. Like the
nameserver/broker/proxy tools, these read the configured default
cluster (the service is not instance-scoped server-side), so they join
the platform-level instanceId exemption on both the Java and rmqctl
catalog sides; the regenerated catalog gives rmqctl litetopic
list/session/quota.
extendTTL deliberately stays out: it is the first LiteTopic mutation
and deserves its own reviewed slice with dry-run/apply semantics.
Co-Authored-By: Claude Code <[email protected]>
---
rmqctl/internal/catalog/catalog.go | 3 +
rmqctl/internal/catalog/catalog_gen.go | 46 +++++-
.../studio/ops/ai/tool/catalog/ToolCatalog.java | 13 +-
.../contract/litetopic/LiteTopicListInput.java | 20 +++
.../tool/contract/litetopic/LiteTopicListItem.java | 52 ++++++
.../contract/litetopic/LiteTopicQuotaInput.java | 20 +++
.../contract/litetopic/LiteTopicQuotaOutput.java | 53 ++++++
.../contract/litetopic/LiteTopicSessionInput.java | 20 +++
.../contract/litetopic/LiteTopicSessionOutput.java | 75 +++++++++
.../litetopic/LiteTopicListToolHandler.java | 50 ++++++
.../litetopic/LiteTopicQuotaToolHandler.java | 47 ++++++
.../litetopic/LiteTopicSessionToolHandler.java | 47 ++++++
.../resources/tool-catalog/tools/litetopic.yaml | 183 +++++++++++++++++++++
.../litetopic/LiteTopicListToolHandlerTest.java | 78 +++++++++
.../litetopic/LiteTopicQuotaToolHandlerTest.java | 85 ++++++++++
.../litetopic/LiteTopicSessionToolHandlerTest.java | 97 +++++++++++
.../tool/service/ToolOutputSchemaContractTest.java | 15 ++
17 files changed, 900 insertions(+), 4 deletions(-)
diff --git a/rmqctl/internal/catalog/catalog.go
b/rmqctl/internal/catalog/catalog.go
index ff42ab2ce..cc0a86efb 100644
--- a/rmqctl/internal/catalog/catalog.go
+++ b/rmqctl/internal/catalog/catalog.go
@@ -57,6 +57,9 @@ var platformToolNames = map[string]struct{}{
"rmq.broker.config": {},
"rmq.proxy.list": {},
"rmq.proxy.config": {},
+ "rmq.litetopic.list": {},
+ "rmq.litetopic.session": {},
+ "rmq.litetopic.quota": {},
}
// IsPlatformTool reports whether the named tool is exempt from carrying an
diff --git a/rmqctl/internal/catalog/catalog_gen.go
b/rmqctl/internal/catalog/catalog_gen.go
index bfd0c07b9..b8eebdcc5 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:
"bf33ada8149a42a0f44d3056b999841ae1cc1612735bfe0dc7fa20f5b707a17c",
+ Digest:
"378a711779f7ea73703c07cfc8fa757300c8fe0c77d967970564ef409834a85d",
Tools: []Tool{
{
Name: "rmq.acl.list",
@@ -369,6 +369,50 @@ var defaultDocument = Document{
},
ViewHint: "object",
},
+ {
+ Name: "rmq.litetopic.list",
+ CLI: CLI{Resource: "litetopic", Verb:
"list"},
+ Description: "List LiteTopic pattern
aggregates served by the configured default cluster's broker lite admin API
(studio.rocketmq.namesrv-addr): per pattern the topic count, consumer count,
total backlog, average TTL, TTL status, last active time and session ids.
Optional pattern prefix and namespace filters. Absent statistics mean the
broker could not report them, not zero. Fails with 501 when the cluster does
not support LiteTopic.",
+ RiskLevel: "L1",
+ Permission: "litetopic:read",
+ RequiredCapabilities: []string{},
+ InputSchema: InputSchema{
+ Fields: []Field{
+ {Name: "pattern", Flag: "pattern",
Description: "LiteTopic pattern/prefix filter, e.g. \"chat/sess-\".", Kind:
StringField, MinLength: 1},
+ {Name: "namespace", Flag: "namespace",
Description: "Namespace filter.", Kind: StringField, MinLength: 1},
+ },
+ },
+ ViewHint: "table",
+ TableDataKey: "items",
+ },
+ {
+ Name: "rmq.litetopic.session",
+ CLI: CLI{Resource: "litetopic", Verb:
"session"},
+ Description: "Describe one LiteTopic session
on the configured default cluster: owning client, parent topic, consumer group,
create/last-active time, TTL and remaining TTL, message and Pop progress
counters, and the session's individual lite topics. Fails with 501 when the
cluster does not support LiteTopic.",
+ RiskLevel: "L1",
+ Permission: "litetopic:read",
+ RequiredCapabilities: []string{},
+ InputSchema: InputSchema{
+ Fields: []Field{
+ {Name: "sessionId", Flag: "session-id",
Description: "Session id as listed by rmq.litetopic.list.", Kind: StringField,
Required: true, MinLength: 1},
+ },
+ },
+ ViewHint: "object",
+ },
+ {
+ Name: "rmq.litetopic.quota",
+ CLI: CLI{Resource: "litetopic", Verb:
"quota"},
+ Description: "Read the LiteTopic quota
watermark of the configured default cluster: current/max topic, session and
creation-rate counts, usage rates, default/max TTL, remaining quota and
consumer density, optionally filtered by namespace. Every field is optional —
brokers may report only part of the watermark. Fails with 501 when the cluster
does not support LiteTopic.",
+ RiskLevel: "L1",
+ Permission: "litetopic:read",
+ RequiredCapabilities: []string{},
+ InputSchema: InputSchema{
+ Fields: []Field{
+ {Name: "namespace", Flag: "namespace",
Description: "Namespace filter.", Kind: StringField, MinLength: 1},
+ },
+ },
+ ViewHint: "object",
+ },
{
Name: "rmq.message.query",
CLI: CLI{Resource: "message", Verb:
"query"},
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/catalog/ToolCatalog.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/catalog/ToolCatalog.java
index 6e0fc8248..4c5390d97 100644
---
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/catalog/ToolCatalog.java
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/catalog/ToolCatalog.java
@@ -57,8 +57,10 @@ public class ToolCatalog {
/**
* Platform-level tools that are not addressed by a Studio instance: the
four global tools
- * (cluster/dashboard/audit/alert) plus the seven physical-infrastructure
tools
- * (nameserver/broker/proxy). They are exempt from the mandatory {@code
instanceId} argument.
+ * (cluster/dashboard/audit/alert), the seven physical-infrastructure tools
+ * (nameserver/broker/proxy) and the three LiteTopic reads, whose
server-side source is the
+ * configured default cluster's broker lite admin API rather than an
Instance. They are
+ * exempt from the mandatory {@code instanceId} argument.
*/
static final Set<String> INSTANCE_ID_EXEMPT_TOOLS = Set.of(
"rmq.cluster.list",
@@ -71,7 +73,12 @@ public class ToolCatalog {
"rmq.broker.describe",
"rmq.broker.config",
"rmq.proxy.list",
- "rmq.proxy.config");
+ "rmq.proxy.config",
+ // LiteTopic reads come from the configured default cluster's
broker lite admin
+ // API, which is not instance-scoped server-side; see
LiteTopicService.
+ "rmq.litetopic.list",
+ "rmq.litetopic.session",
+ "rmq.litetopic.quota");
private static final ObjectMapper YAML_MAPPER = new ObjectMapper(new
YAMLFactory());
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicListInput.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicListInput.java
new file mode 100644
index 000000000..512a04707
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicListInput.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic;
+
+public record LiteTopicListInput(String pattern, String namespace) {
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicListItem.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicListItem.java
new file mode 100644
index 000000000..f6b0362b9
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicListItem.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicItemVO;
+
+import java.util.List;
+
+/**
+ * One pattern-level LiteTopic aggregate. Statistics the broker cannot report
stay absent
+ * instead of being zero-filled: an unknown backlog is not a zero backlog.
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public record LiteTopicListItem(
+ String topicPattern,
+ String namespace,
+ Integer topicCount,
+ Integer consumerCount,
+ Long totalBacklog,
+ Long averageTTL,
+ String ttlStatus,
+ Long lastActiveTime,
+ List<String> sessionIds) {
+
+ public static LiteTopicListItem from(LiteTopicItemVO vo) {
+ return new LiteTopicListItem(
+ vo.getTopicPattern(),
+ vo.getNamespace(),
+ vo.getTopicCount(),
+ vo.getConsumerCount(),
+ vo.getTotalBacklog(),
+ vo.getAverageTTL(),
+ vo.getTtlStatus(),
+ vo.getLastActiveTime(),
+ vo.getSessionIds() == null ? null :
List.copyOf(vo.getSessionIds()));
+ }
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicQuotaInput.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicQuotaInput.java
new file mode 100644
index 000000000..3b9fcdd91
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicQuotaInput.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic;
+
+public record LiteTopicQuotaInput(String namespace) {
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicQuotaOutput.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicQuotaOutput.java
new file mode 100644
index 000000000..18df1b59e
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicQuotaOutput.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicQuotaVO;
+
+/** LiteTopic quota watermark. Every field is optional: brokers may report
only part of it. */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public record LiteTopicQuotaOutput(
+ Integer currentTopicCount,
+ Integer maxTopicCount,
+ Integer currentSessionCount,
+ Integer maxSessionCount,
+ Integer currentCreationRate,
+ Integer maxCreationRate,
+ Double usageRate,
+ Double sessionUsageRate,
+ Long defaultTTL,
+ Long maxTTL,
+ Integer remainingQuota,
+ Double consumerDensity) {
+
+ public static LiteTopicQuotaOutput from(LiteTopicQuotaVO vo) {
+ return new LiteTopicQuotaOutput(
+ vo.getCurrentTopicCount(),
+ vo.getMaxTopicCount(),
+ vo.getCurrentSessionCount(),
+ vo.getMaxSessionCount(),
+ vo.getCurrentCreationRate(),
+ vo.getMaxCreationRate(),
+ vo.getUsageRate(),
+ vo.getSessionUsageRate(),
+ vo.getDefaultTTL(),
+ vo.getMaxTTL(),
+ vo.getRemainingQuota(),
+ vo.getConsumerDensity());
+ }
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicSessionInput.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicSessionInput.java
new file mode 100644
index 000000000..6aaa10535
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicSessionInput.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic;
+
+public record LiteTopicSessionInput(String sessionId) {
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicSessionOutput.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicSessionOutput.java
new file mode 100644
index 000000000..3db576f27
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/contract/litetopic/LiteTopicSessionOutput.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicSessionVO;
+
+import java.util.List;
+
+/**
+ * One LiteTopic session with its per-topic entries. Fields the broker cannot
report stay
+ * absent rather than being invented.
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public record LiteTopicSessionOutput(
+ String sessionId,
+ String clientId,
+ String clientAddress,
+ String parentTopic,
+ String consumerGroup,
+ Long createTime,
+ Long lastActiveTime,
+ Long ttl,
+ Long ttlRemaining,
+ String status,
+ Long totalMessages,
+ Long consumedMessages,
+ Long pendingMessages,
+ Integer popProgress,
+ Integer liteTopicCreationCount,
+ List<Entry> liteTopics) {
+
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ public record Entry(String topicName, String status, Long ttlRemaining) {
+ }
+
+ public static LiteTopicSessionOutput from(LiteTopicSessionVO vo) {
+ return new LiteTopicSessionOutput(
+ vo.getSessionId(),
+ vo.getClientId(),
+ vo.getClientAddress(),
+ vo.getParentTopic(),
+ vo.getConsumerGroup(),
+ vo.getCreateTime(),
+ vo.getLastActiveTime(),
+ vo.getTtl(),
+ vo.getTtlRemaining(),
+ vo.getStatus(),
+ vo.getTotalMessages(),
+ vo.getConsumedMessages(),
+ vo.getPendingMessages(),
+ vo.getPopProgress(),
+ vo.getLiteTopicCreationCount(),
+ vo.getLiteTopics() == null
+ ? null
+ : vo.getLiteTopics().stream()
+ .map(topic -> new Entry(
+ topic.getTopicName(),
topic.getStatus(), topic.getTtlRemaining()))
+ .toList());
+ }
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicListToolHandler.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicListToolHandler.java
new file mode 100644
index 000000000..491cb305d
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicListToolHandler.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.handler.litetopic;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicService;
+import org.apache.rocketmq.studio.ops.ai.tool.contract.common.ListOutput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicListItem;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicListInput;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolHandler;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class LiteTopicListToolHandler implements
ToolHandler<LiteTopicListInput, ListOutput<LiteTopicListItem>> {
+
+ private final LiteTopicService liteTopicService;
+
+ @Override
+ public String name() {
+ return "rmq.litetopic.list";
+ }
+
+ @Override
+ public Class<LiteTopicListInput> inputType() {
+ return LiteTopicListInput.class;
+ }
+
+ @Override
+ public ListOutput<LiteTopicListItem> execute(LiteTopicListInput input,
ToolExecutionContext context) {
+ return new
ListOutput<>(liteTopicService.listLiteTopics(input.pattern(),
input.namespace()).stream()
+ .map(LiteTopicListItem::from)
+ .toList());
+ }
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicQuotaToolHandler.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicQuotaToolHandler.java
new file mode 100644
index 000000000..74e7de599
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicQuotaToolHandler.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.handler.litetopic;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicService;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicQuotaInput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicQuotaOutput;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolHandler;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class LiteTopicQuotaToolHandler implements
ToolHandler<LiteTopicQuotaInput, LiteTopicQuotaOutput> {
+
+ private final LiteTopicService liteTopicService;
+
+ @Override
+ public String name() {
+ return "rmq.litetopic.quota";
+ }
+
+ @Override
+ public Class<LiteTopicQuotaInput> inputType() {
+ return LiteTopicQuotaInput.class;
+ }
+
+ @Override
+ public LiteTopicQuotaOutput execute(LiteTopicQuotaInput input,
ToolExecutionContext context) {
+ return
LiteTopicQuotaOutput.from(liteTopicService.getQuota(input.namespace()));
+ }
+}
diff --git
a/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicSessionToolHandler.java
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicSessionToolHandler.java
new file mode 100644
index 000000000..0dd566db1
--- /dev/null
+++
b/server/src/main/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicSessionToolHandler.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.handler.litetopic;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicService;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicSessionInput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicSessionOutput;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolHandler;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class LiteTopicSessionToolHandler implements
ToolHandler<LiteTopicSessionInput, LiteTopicSessionOutput> {
+
+ private final LiteTopicService liteTopicService;
+
+ @Override
+ public String name() {
+ return "rmq.litetopic.session";
+ }
+
+ @Override
+ public Class<LiteTopicSessionInput> inputType() {
+ return LiteTopicSessionInput.class;
+ }
+
+ @Override
+ public LiteTopicSessionOutput execute(LiteTopicSessionInput input,
ToolExecutionContext context) {
+ return
LiteTopicSessionOutput.from(liteTopicService.getSession(input.sessionId()));
+ }
+}
diff --git a/server/src/main/resources/tool-catalog/tools/litetopic.yaml
b/server/src/main/resources/tool-catalog/tools/litetopic.yaml
new file mode 100644
index 000000000..9554899ce
--- /dev/null
+++ b/server/src/main/resources/tool-catalog/tools/litetopic.yaml
@@ -0,0 +1,183 @@
+version: 2.0.0
+tools:
+ - name: rmq.litetopic.list
+ cli:
+ resource: litetopic
+ verb: list
+ description: "List LiteTopic pattern aggregates served by the configured
default cluster's broker lite admin API (studio.rocketmq.namesrv-addr): per
pattern the topic count, consumer count, total backlog, average TTL, TTL
status, last active time and session ids. Optional pattern prefix and namespace
filters. Absent statistics mean the broker could not report them, not zero.
Fails with 501 when the cluster does not support LiteTopic."
+ riskLevel: L1
+ permission: litetopic:read
+ requiredCapabilities: []
+ inputSchema:
+ type: object
+ required: []
+ additionalProperties: false
+ properties:
+ pattern:
+ type: string
+ description: LiteTopic pattern/prefix filter, e.g. "chat/sess-".
+ minLength: 1
+ namespace:
+ type: string
+ description: Namespace filter.
+ minLength: 1
+ outputSchema:
+ type: object
+ required:
+ - items
+ additionalProperties: false
+ properties:
+ items:
+ type: array
+ items:
+ type: object
+ required:
+ - topicPattern
+ additionalProperties: false
+ properties:
+ topicPattern:
+ type: string
+ minLength: 1
+ namespace:
+ type: string
+ topicCount:
+ type: integer
+ consumerCount:
+ type: integer
+ totalBacklog:
+ type: integer
+ averageTTL:
+ type: integer
+ ttlStatus:
+ type: string
+ lastActiveTime:
+ type: integer
+ description: Epoch milliseconds.
+ sessionIds:
+ type: array
+ items:
+ type: string
+ viewHint: table
+ deprecated: false
+ - name: rmq.litetopic.session
+ cli:
+ resource: litetopic
+ verb: session
+ description: "Describe one LiteTopic session on the configured default
cluster: owning client, parent topic, consumer group, create/last-active time,
TTL and remaining TTL, message and Pop progress counters, and the session's
individual lite topics. Fails with 501 when the cluster does not support
LiteTopic."
+ riskLevel: L1
+ permission: litetopic:read
+ requiredCapabilities: []
+ inputSchema:
+ type: object
+ required:
+ - sessionId
+ additionalProperties: false
+ properties:
+ sessionId:
+ type: string
+ description: Session id as listed by rmq.litetopic.list.
+ minLength: 1
+ outputSchema:
+ type: object
+ required:
+ - sessionId
+ additionalProperties: false
+ properties:
+ sessionId:
+ type: string
+ minLength: 1
+ clientId:
+ type: string
+ clientAddress:
+ type: string
+ parentTopic:
+ type: string
+ consumerGroup:
+ type: string
+ createTime:
+ type: integer
+ description: Epoch milliseconds.
+ lastActiveTime:
+ type: integer
+ description: Epoch milliseconds.
+ ttl:
+ type: integer
+ ttlRemaining:
+ type: integer
+ status:
+ type: string
+ totalMessages:
+ type: integer
+ consumedMessages:
+ type: integer
+ pendingMessages:
+ type: integer
+ popProgress:
+ type: integer
+ liteTopicCreationCount:
+ type: integer
+ liteTopics:
+ type: array
+ items:
+ type: object
+ required:
+ - topicName
+ additionalProperties: false
+ properties:
+ topicName:
+ type: string
+ minLength: 1
+ status:
+ type: string
+ ttlRemaining:
+ type: integer
+ viewHint: object
+ deprecated: false
+ - name: rmq.litetopic.quota
+ cli:
+ resource: litetopic
+ verb: quota
+ description: "Read the LiteTopic quota watermark of the configured default
cluster: current/max topic, session and creation-rate counts, usage rates,
default/max TTL, remaining quota and consumer density, optionally filtered by
namespace. Every field is optional — brokers may report only part of the
watermark. Fails with 501 when the cluster does not support LiteTopic."
+ riskLevel: L1
+ permission: litetopic:read
+ requiredCapabilities: []
+ inputSchema:
+ type: object
+ required: []
+ additionalProperties: false
+ properties:
+ namespace:
+ type: string
+ description: Namespace filter.
+ minLength: 1
+ outputSchema:
+ type: object
+ required: []
+ additionalProperties: false
+ properties:
+ currentTopicCount:
+ type: integer
+ maxTopicCount:
+ type: integer
+ currentSessionCount:
+ type: integer
+ maxSessionCount:
+ type: integer
+ currentCreationRate:
+ type: integer
+ maxCreationRate:
+ type: integer
+ usageRate:
+ type: number
+ sessionUsageRate:
+ type: number
+ defaultTTL:
+ type: integer
+ maxTTL:
+ type: integer
+ remainingQuota:
+ type: integer
+ consumerDensity:
+ type: number
+ viewHint: object
+ deprecated: false
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicListToolHandlerTest.java
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicListToolHandlerTest.java
new file mode 100644
index 000000000..eb5661873
--- /dev/null
+++
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicListToolHandlerTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.handler.litetopic;
+
+import org.apache.rocketmq.studio.instance.topic.LiteTopicItemVO;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicService;
+import org.apache.rocketmq.studio.ops.ai.tool.contract.common.ListOutput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicListItem;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicListInput;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class LiteTopicListToolHandlerTest {
+
+ @Mock
+ private LiteTopicService liteTopicService;
+
+ @InjectMocks
+ private LiteTopicListToolHandler handler;
+
+ @Test
+ void passesFiltersThroughAndKeepsUnreportableStatisticsAbsentTest() {
+ when(liteTopicService.listLiteTopics("chat/sess-",
"ns-a")).thenReturn(List.of(
+ LiteTopicItemVO.builder()
+ .topicPattern("chat/sess-")
+ .namespace("ns-a")
+ .topicCount(12)
+ .consumerCount(3)
+ .totalBacklog(120L)
+ .averageTTL(3600L)
+ .ttlStatus("ACTIVE")
+ .lastActiveTime(1789092600000L)
+ .sessionIds(List.of("sess-1", "sess-2"))
+ .build(),
+ LiteTopicItemVO.builder()
+ .topicPattern("orders/")
+ .build()));
+
+ ListOutput<LiteTopicListItem> result = handler.execute(
+ new LiteTopicListInput("chat/sess-", "ns-a"), context());
+
+ verify(liteTopicService).listLiteTopics("chat/sess-", "ns-a");
+ assertThat(result.items()).containsExactly(
+ new LiteTopicListItem("chat/sess-", "ns-a", 12, 3, 120L,
3600L, "ACTIVE",
+ 1789092600000L, List.of("sess-1", "sess-2")),
+ new LiteTopicListItem("orders/", null, null, null, null, null,
null, null, null));
+ }
+
+ private static ToolExecutionContext context() {
+ return ToolExecutionContext.of(null, null, Map.of());
+ }
+}
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicQuotaToolHandlerTest.java
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicQuotaToolHandlerTest.java
new file mode 100644
index 000000000..aca07b58b
--- /dev/null
+++
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicQuotaToolHandlerTest.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.handler.litetopic;
+
+import org.apache.rocketmq.studio.instance.topic.LiteTopicQuotaVO;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicService;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicQuotaInput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicQuotaOutput;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class LiteTopicQuotaToolHandlerTest {
+
+ @Mock
+ private LiteTopicService liteTopicService;
+
+ @InjectMocks
+ private LiteTopicQuotaToolHandler handler;
+
+ @Test
+ void mapsTheFullWatermarkTest() {
+
when(liteTopicService.getQuota("ns-a")).thenReturn(LiteTopicQuotaVO.builder()
+ .currentTopicCount(120)
+ .maxTopicCount(1000)
+ .currentSessionCount(30)
+ .maxSessionCount(100)
+ .currentCreationRate(5)
+ .maxCreationRate(50)
+ .usageRate(0.12)
+ .sessionUsageRate(0.3)
+ .defaultTTL(3600L)
+ .maxTTL(86400L)
+ .remainingQuota(880)
+ .consumerDensity(2.5)
+ .build());
+
+ LiteTopicQuotaOutput output = handler.execute(new
LiteTopicQuotaInput("ns-a"), context());
+
+ verify(liteTopicService).getQuota("ns-a");
+ assertThat(output).isEqualTo(new LiteTopicQuotaOutput(
+ 120, 1000, 30, 100, 5, 50, 0.12, 0.3, 3600L, 86400L, 880,
2.5));
+ }
+
+ @Test
+ void keepsPartialWatermarksPartialTest() {
+
when(liteTopicService.getQuota(null)).thenReturn(LiteTopicQuotaVO.builder()
+ .currentTopicCount(7)
+ .build());
+
+ LiteTopicQuotaOutput output = handler.execute(new
LiteTopicQuotaInput(null), context());
+
+ assertThat(output.currentTopicCount()).isEqualTo(7);
+ assertThat(output.maxTopicCount()).isNull();
+ assertThat(output.usageRate()).isNull();
+ }
+
+ private static ToolExecutionContext context() {
+ return ToolExecutionContext.of(null, null, Map.of());
+ }
+}
diff --git
a/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicSessionToolHandlerTest.java
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicSessionToolHandlerTest.java
new file mode 100644
index 000000000..e78b1de12
--- /dev/null
+++
b/server/src/test/java/org/apache/rocketmq/studio/ops/ai/tool/handler/litetopic/LiteTopicSessionToolHandlerTest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.studio.ops.ai.tool.handler.litetopic;
+
+import org.apache.rocketmq.studio.instance.topic.LiteTopicService;
+import org.apache.rocketmq.studio.instance.topic.LiteTopicSessionVO;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicSessionInput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicSessionOutput;
+import org.apache.rocketmq.studio.ops.ai.tool.core.ToolExecutionContext;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class LiteTopicSessionToolHandlerTest {
+
+ @Mock
+ private LiteTopicService liteTopicService;
+
+ @InjectMocks
+ private LiteTopicSessionToolHandler handler;
+
+ @Test
+ void mapsTheSessionAndItsEntriesTest() {
+ LiteTopicSessionVO.SessionLiteTopic entry = new
LiteTopicSessionVO.SessionLiteTopic();
+ entry.setTopicName("chat/sess-1/0");
+ entry.setStatus("ACTIVE");
+ entry.setTtlRemaining(1800L);
+
when(liteTopicService.getSession("sess-1")).thenReturn(LiteTopicSessionVO.builder()
+ .sessionId("sess-1")
+ .clientId("client-1")
+ .clientAddress("10.0.0.1:5678")
+ .parentTopic("chat")
+ .consumerGroup("cg-chat")
+ .createTime(1789092000000L)
+ .lastActiveTime(1789092600000L)
+ .ttl(3600L)
+ .ttlRemaining(1800L)
+ .status("ACTIVE")
+ .totalMessages(10L)
+ .consumedMessages(4L)
+ .pendingMessages(6L)
+ .popProgress(40)
+ .liteTopicCreationCount(1)
+ .liteTopics(List.of(entry))
+ .build());
+
+ LiteTopicSessionOutput output = handler.execute(new
LiteTopicSessionInput("sess-1"), context());
+
+ verify(liteTopicService).getSession("sess-1");
+ assertThat(output).isEqualTo(new LiteTopicSessionOutput(
+ "sess-1", "client-1", "10.0.0.1:5678", "chat", "cg-chat",
+ 1789092000000L, 1789092600000L, 3600L, 1800L, "ACTIVE",
+ 10L, 4L, 6L, 40, 1,
+ List.of(new LiteTopicSessionOutput.Entry("chat/sess-1/0",
"ACTIVE", 1800L))));
+ }
+
+ @Test
+ void keepsSparseSessionsPartialInsteadOfInventingFieldsTest() {
+
when(liteTopicService.getSession("sess-2")).thenReturn(LiteTopicSessionVO.builder()
+ .sessionId("sess-2")
+ .build());
+
+ LiteTopicSessionOutput output = handler.execute(new
LiteTopicSessionInput("sess-2"), context());
+
+ assertThat(output.sessionId()).isEqualTo("sess-2");
+ assertThat(output.clientId()).isNull();
+ assertThat(output.liteTopics()).isNull();
+ }
+
+ private static ToolExecutionContext context() {
+ return ToolExecutionContext.of(null, null, Map.of());
+ }
+}
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 96769814d..2fe9839e0 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
@@ -35,6 +35,9 @@ import
org.apache.rocketmq.studio.ops.ai.tool.contract.broker.BrokerConfigOutput
import
org.apache.rocketmq.studio.ops.ai.tool.contract.broker.BrokerDescribeOutput;
import org.apache.rocketmq.studio.ops.ai.tool.contract.cluster.ClusterListItem;
import org.apache.rocketmq.studio.ops.ai.tool.contract.common.ListOutput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicListItem;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicQuotaOutput;
+import
org.apache.rocketmq.studio.ops.ai.tool.contract.litetopic.LiteTopicSessionOutput;
import org.apache.rocketmq.studio.ops.ai.tool.contract.common.MutationOutput;
import org.apache.rocketmq.studio.ops.ai.tool.contract.common.PageOutput;
import org.apache.rocketmq.studio.ops.ai.tool.contract.group.GroupDetailOutput;
@@ -151,6 +154,18 @@ class ToolOutputSchemaContractTest {
new AlertRuleListItem(2L, "draft-rule", null, null,
0.0, null, null, List.of(), false, null)))));
+ samples.put("rmq.litetopic.list", List.of(new ListOutput<>(List.of(
+ new LiteTopicListItem("chat/sess-", "ns-a", 12, 3, 120L,
3600L, "ACTIVE",
+ 1789092600000L, List.of("sess-1")),
+ new LiteTopicListItem("orders/", null, null, null, null, null,
null, null, null)))));
+ samples.put("rmq.litetopic.session", List.of(new
LiteTopicSessionOutput(
+ "sess-1", "client-1", "10.0.0.1:5678", "chat", "cg-chat",
+ 1789092000000L, 1789092600000L, 3600L, 1800L, "ACTIVE",
+ 10L, 4L, 6L, 40, 1,
+ List.of(new LiteTopicSessionOutput.Entry("chat/sess-1/0",
"ACTIVE", 1800L)))));
+ samples.put("rmq.litetopic.quota", List.of(new LiteTopicQuotaOutput(
+ 120, 1000, 30, 100, 5, 50, 0.12, 0.3, 3600L, 86400L, 880,
2.5)));
+
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",
"orders", INSTANCE, "{}", "SUCCESS", null)))));