You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@hertzbeat.apache.org by li...@apache.org on 2025/11/01 13:22:45 UTC

(hertzbeat) branch master updated: refactor ai agent and fix bug, update doc (#3836)

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

liuhongyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git


The following commit(s) were added to refs/heads/master by this push:
     new fb4b665c85 refactor ai agent and fix bug, update doc (#3836)
fb4b665c85 is described below

commit fb4b665c85ef90424ea8c387688f6d6dfb28407a
Author: Tomsun28 <to...@outlook.com>
AuthorDate: Sat Nov 1 21:22:42 2025 +0800

    refactor ai agent and fix bug, update doc (#3836)
    
    Signed-off-by: tomsun28 <to...@outlook.com>
    Co-authored-by: aias00 <li...@apache.org>
---
 hertzbeat-ai/pom.xml                               |   5 +-
 .../ai/adapters/AlertDefineServiceAdapter.java     |  81 ----
 .../hertzbeat/ai/adapters/AlertServiceAdapter.java |  60 ---
 .../ai/adapters/MetricsServiceAdapter.java         |  55 ---
 .../ai/adapters/MonitorServiceAdapter.java         |  71 ---
 .../impl/AlertDefineServiceAdapterImpl.java        | 257 -----------
 .../ai/adapters/impl/AlertServiceAdapterImpl.java  | 141 ------
 .../adapters/impl/MetricsServiceAdapterImpl.java   | 136 ------
 .../adapters/impl/MonitorServiceAdapterImpl.java   | 214 ---------
 .../hertzbeat/ai/config/DynamicOpenAiApiKey.java   |  56 ---
 .../org/apache/hertzbeat/ai/config/LlmConfig.java  |   9 +-
 .../hertzbeat/ai/controller/ChatController.java    |  96 ++---
 .../hertzbeat/ai/dao/ChatConversationDao.java      |  12 +-
 .../apache/hertzbeat/ai/dao/ChatMessageDao.java    |  13 +-
 .../hertzbeat/ai/pojo/dto/ChatRequestContext.java  |   5 +-
 ...ChatResponseDto.java => ChatResponseChunk.java} |  15 +-
 .../hertzbeat/ai/pojo/dto/ConversationDto.java     |  53 ---
 .../apache/hertzbeat/ai/pojo/dto/Hierarchy.java    |  87 ----
 .../apache/hertzbeat/ai/pojo/dto/MessageDto.java   |  52 ---
 .../hertzbeat/ai/service/AiConfigService.java      |  60 ---
 .../hertzbeat/ai/service/ConversationService.java  |  34 +-
 .../ai/service/impl/AiConfigServiceImpl.java       | 100 -----
 .../impl/ChatClientProviderServiceImpl.java        |  16 +-
 .../ai/service/impl/ConversationServiceImpl.java   | 216 +++-------
 .../ai/tools/impl/AlertDefineToolsImpl.java        |  68 ++-
 .../hertzbeat/ai/tools/impl/AlertToolsImpl.java    |  10 +-
 .../hertzbeat/ai/tools/impl/MetricsToolsImpl.java  |  15 +-
 .../hertzbeat/ai/tools/impl/MonitorToolsImpl.java  |  52 ++-
 .../apache/hertzbeat/ai/utils/UtilityClass.java    | 198 +--------
 .../notice/impl/EmailAlertNotifyHandlerImpl.java   |   2 +-
 .../hertzbeat/alert/service/SmsClientFactory.java  |   4 +-
 .../alert/service/impl/AlibabaSmsClientImpl.java   |   4 +-
 .../alert/service/impl/AwsSmsClientImpl.java       |   2 +-
 .../alert/service/impl/SmsLocalSmsClientImpl.java  |   2 +-
 .../alert/service/impl/TencentSmsClientImpl.java   |   2 +-
 .../alert/service/impl/TwilioSmsClientImpl.java    |   4 +-
 .../alert/service/impl/UniSmsClientImpl.java       |   4 +-
 .../impl/EmailAlertNotifyHandlerImplTest.java      |   2 +-
 .../alert/service/AwsSmsClientImplTest.java        |   2 +-
 .../alert/service/SmsClientFactoryTest.java        |   6 +-
 .../alert/service/TwilioSmsClientImplTest.java     |   4 +-
 .../service/impl/SmsLocalSmsClientImplTest.java    |   4 +-
 .../alert/service/impl/UniSmsClientImplTest.java   |   4 +-
 .../common/entity/ai/ChatConversation.java         |  56 +--
 .../hertzbeat/common/entity/ai/ChatMessage.java    |  58 +--
 .../common/entity}/dto/MailServerConfig.java       |   2 +-
 .../common/entity}/dto/ModelProviderConfig.java    |  11 +-
 .../entity/dto/sms}/AlibabaSmsProperties.java      |   2 +-
 .../common/entity/dto/sms}/AwsSmsProperties.java   |   2 +-
 .../common/entity/dto/sms}/SmsConfig.java          |   4 +-
 .../entity/dto/sms}/SmslocalSmsProperties.java     |   2 +-
 .../entity/dto/sms}/TencentSmsProperties.java      |   4 +-
 .../entity/dto/sms}/TwilioSmsProperties.java       |   4 +-
 .../common/entity/dto/sms}/UniSmsProperties.java   |   4 +-
 hertzbeat-manager/pom.xml                          |   5 -
 .../hertzbeat/manager/config/AiProperties.java     |  60 ---
 .../hertzbeat/manager/controller/AiController.java |  68 ---
 .../manager/pojo/dto/OpenAiRequestParamDTO.java    |  70 ---
 .../hertzbeat/manager/pojo/dto/OpenAiResponse.java | 115 -----
 .../hertzbeat/manager/pojo/dto/TemplateConfig.java |   1 +
 .../hertzbeat/manager/service/ai/AiService.java    |  44 --
 .../manager/service/ai/AlibabaAiServiceImpl.java   | 118 -----
 .../manager/service/ai/KimiAiServiceImpl.java      |  96 -----
 .../manager/service/ai/OllamaAiService.java        |  95 ----
 .../manager/service/ai/OpenRouterServiceImpl.java  |  97 -----
 .../manager/service/ai/SparkDeskAiServiceImpl.java | 104 -----
 .../manager/service/ai/ZhiPuServiceImpl.java       | 100 -----
 .../service/ai/factory/AiServiceFactoryImpl.java   |  64 ---
 .../service/impl/MailGeneralConfigServiceImpl.java |   2 +-
 .../impl/ModelProviderConfigServiceImpl.java       |   2 +-
 .../service/impl/SmsGeneralConfigServiceImpl.java  |   3 +-
 .../manager/controller/AiControllerTest.java       |  88 ----
 .../controller/MetricsFavoriteControllerTest.java  |   2 +-
 .../manager/service/AiServiceFactoryTest.java      | 125 ------
 .../manager/service/ConfigServiceTest.java         |   2 +-
 .../manager/service/KimiAiServiceTest.java         |  28 --
 .../service/MailGeneralConfigServiceTest.java      |   2 +-
 .../service/SmsGeneralConfigServiceTest.java       |   2 +-
 .../manager/service/ZhiPuServiceTest.java          |  27 --
 hertzbeat-startup/pom.xml                          |   6 +
 home/README.md                                     |   6 +-
 home/docs/help/{ai_agent_chat.md => ai_agent.md}   |  35 +-
 home/docs/help/ai_config.md                        |  81 ----
 home/docs/help/mcp_sse_server.md                   |   6 +-
 .../current/help/ai_agent.md                       | 357 +++++++++++++++
 .../current/help/ai_config.md                      |  81 ----
 .../current/help/mcp_sse_server.md                 |  97 +++++
 home/sidebars.json                                 |   5 +-
 pom.xml                                            |   6 +
 script/application.yml                             |  68 ++-
 script/assembly/server/assembly-docker.xml         |   2 +-
 script/assembly/server/assembly-linux-amd64.xml    |   2 +-
 script/assembly/server/assembly-linux-arm64.xml    |   2 +-
 script/assembly/server/assembly-macos-amd64.xml    |   2 +-
 script/assembly/server/assembly-macos-arm64.xml    |   2 +-
 script/assembly/server/assembly-windows-64.xml     |   2 +-
 script/assembly/server/assembly.xml                |   2 +-
 .../hertzbeat-mysql-iotdb/conf/application.yml     |   7 -
 .../hertzbeat-mysql-tdengine/conf/application.yml  |   7 -
 .../conf/application.yml                           |   7 -
 .../conf/application.yml                           |   7 -
 web-app/src/app/layout/basic/basic.component.less  |  32 +-
 web-app/src/app/layout/basic/basic.component.ts    |   8 +-
 .../layout/basic/widgets/chat-input.component.ts   |  89 ++++
 .../app/layout/basic/widgets/search.component.less |  74 ----
 .../app/layout/basic/widgets/search.component.ts   | 181 --------
 web-app/src/app/layout/layout.module.ts            |   4 +-
 web-app/src/app/pojo/ModelProviderConfig.ts        |   2 -
 .../app/routes/dashboard/dashboard.component.html  |   2 +-
 .../app/routes/dashboard/dashboard.component.less  |   2 +-
 .../app/routes/dashboard/dashboard.component.ts    |   4 +-
 web-app/src/app/service/ai-chat.service.ts         |  33 +-
 .../shared/components/ai-chat/ai-chat.module.ts    |   6 +-
 .../shared/components/ai-chat/chat.component.html  | 107 +++--
 .../shared/components/ai-chat/chat.component.less  | 204 ++++++---
 .../shared/components/ai-chat/chat.component.ts    | 203 +++++----
 .../app/shared/services/ai-chat-modal.service.ts   |   6 +-
 web-app/src/assets/app-data.json                   |   7 +
 web-app/src/assets/i18n/en-US.json                 |  61 ++-
 web-app/src/assets/i18n/ja-JP.json                 |  61 ++-
 web-app/src/assets/i18n/pt-BR.json                 | 477 +++++++++------------
 web-app/src/assets/i18n/zh-CN.json                 |  61 ++-
 web-app/src/assets/i18n/zh-TW.json                 |  61 ++-
 web-app/src/styles/index.less                      |   6 +-
 web-app/src/styles/theme.less                      |   4 +-
 125 files changed, 1774 insertions(+), 4413 deletions(-)

diff --git a/hertzbeat-ai/pom.xml b/hertzbeat-ai/pom.xml
index 0fe8dc1588..de91bf7fa9 100644
--- a/hertzbeat-ai/pom.xml
+++ b/hertzbeat-ai/pom.xml
@@ -65,12 +65,15 @@
         <dependency>
             <groupId>org.apache.hertzbeat</groupId>
             <artifactId>hertzbeat-base</artifactId>
-            <scope>provided</scope>
         </dependency>
 		<dependency>
 			<groupId>org.apache.hertzbeat</groupId>
 			<artifactId>hertzbeat-alerter</artifactId>
 		</dependency>
+        <dependency>
+            <groupId>org.apache.hertzbeat</groupId>
+            <artifactId>hertzbeat-manager</artifactId>
+        </dependency>
 		<dependency>
 			<groupId>com.usthe.sureness</groupId>
 			<artifactId>spring-boot3-starter-sureness</artifactId>
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/AlertDefineServiceAdapter.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/AlertDefineServiceAdapter.java
deleted file mode 100644
index 63ac256b61..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/AlertDefineServiceAdapter.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters;
-
-import org.apache.hertzbeat.ai.pojo.dto.Hierarchy;
-import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
-import org.springframework.data.domain.Page;
-
-import java.util.List;
-
-/**
- * Interface that provides access to alert definition information by retrieving data
- * through the underlying alert define service.
- */
-public interface AlertDefineServiceAdapter {
-
-    /**
-     * Add a new alert rule definition
-     * @param alertDefine Alert definition to add
-     * @return Created alert definition with ID
-     */
-    AlertDefine addAlertDefine(AlertDefine alertDefine);
-
-    /**
-     * Get alert definitions with filtering and pagination
-     * @param search Search term
-     * @param app Monitor type filter
-     * @param enabled Enabled status filter
-     * @param sort Sort field
-     * @param order Sort order
-     * @param pageIndex Page index
-     * @param pageSize Page size
-     * @return Page of alert definitions
-     */
-    Page<AlertDefine> getAlertDefines(String search, String app, Boolean enabled, String sort, String order, int pageIndex, int pageSize);
-
-    /**
-     * Get alert definition by ID
-     * @param id Alert definition ID
-     * @return Alert definition if found
-     */
-    AlertDefine getAlertDefine(Long id);
-
-    /**
-     * Enable or disable alert definition
-     * @param id Alert definition ID
-     * @param enabled Whether to enable
-     */
-    void toggleAlertDefineStatus(Long id, boolean enabled);
-
-    /**
-     * Modify/update an existing alert definition
-     * @param alertDefine Alert definition to update
-     * @return Updated alert definition
-     */
-    AlertDefine modifyAlertDefine(AlertDefine alertDefine);
-
-    /**
-     * Get specific app hierarchy structure
-     * @param app App type
-     * @param lang Language for localization
-     * @return List of hierarchy objects for specific app
-     */
-
-    List<Hierarchy> getAppHierarchy(String app, String lang);
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/AlertServiceAdapter.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/AlertServiceAdapter.java
deleted file mode 100644
index b4dbb196ca..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/AlertServiceAdapter.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters;
-
-import org.apache.hertzbeat.alert.dto.AlertSummary;
-import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
-import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
-import org.springframework.data.domain.Page;
-
-/**
- * Interface that provides access to alert information by retrieving alert data
- * through the underlying alert service.
- */
-public interface AlertServiceAdapter {
-
-    /**
-     * Get single alerts with filtering and pagination
-     * @param status Alert status
-     * @param search Search term
-     * @param sort Sort field
-     * @param order Sort order
-     * @param pageIndex Page index
-     * @param pageSize Page size
-     * @return Page of single alerts
-     */
-    Page<SingleAlert> getSingleAlerts(String status, String search, String sort, String order, int pageIndex, int pageSize);
-
-    /**
-     * Get group alerts with filtering and pagination
-     * @param status Alert status
-     * @param search Search term
-     * @param sort Sort field
-     * @param order Sort order
-     * @param pageIndex Page index
-     * @param pageSize Page size
-     * @return Page of group alerts
-     */
-    Page<GroupAlert> getGroupAlerts(String status, String search, String sort, String order, int pageIndex, int pageSize);
-
-    /**
-     * Get alerts summary statistics
-     * @return Alert summary information
-     */
-    AlertSummary getAlertsSummary();
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/MetricsServiceAdapter.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/MetricsServiceAdapter.java
deleted file mode 100644
index f409596731..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/MetricsServiceAdapter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters;
-
-import org.apache.hertzbeat.common.entity.dto.MetricsData;
-import org.apache.hertzbeat.common.entity.dto.MetricsHistoryData;
-
-/**
- * Interface that provides access to metrics information by retrieving metrics data
- * through the underlying metrics service.
- */
-public interface MetricsServiceAdapter {
-
-    /**
-     * Check warehouse storage server status
-     * @return true if warehouse is available, false otherwise
-     */
-    Boolean getWarehouseStorageServerStatus();
-
-    /**
-     * Query real-time metrics data
-     * @param monitorId Monitor ID
-     * @param metrics Metrics name
-     * @return Real-time metrics data
-     */
-    MetricsData getMetricsData(Long monitorId, String metrics);
-
-    /**
-     * Query historical metrics data
-     * @param monitorId Monitor ID
-     * @param app Monitor type
-     * @param metrics Metrics name
-     * @param metric Metric field name
-     * @param label Label filter
-     * @param history Query historical time period
-     * @param interval Whether to aggregate data
-     * @return Historical metrics data
-     */
-    MetricsHistoryData getMetricHistoryData(Long monitorId, String app, String metrics, String metric, String label, String history, Boolean interval);
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/MonitorServiceAdapter.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/MonitorServiceAdapter.java
deleted file mode 100644
index aad0e2a72b..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/MonitorServiceAdapter.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters;
-
-import org.springframework.data.domain.Page;
-import org.apache.hertzbeat.common.entity.manager.Monitor;
-import org.apache.hertzbeat.common.entity.manager.Param;
-import org.apache.hertzbeat.common.entity.manager.ParamDefine;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Interface that provides access to monitor information by retrieving monitor data
- * through the underlying monitor service.
- */
-public interface MonitorServiceAdapter {
-    Page<Monitor> getMonitors(
-            List<Long> ids,
-            String app,
-            String search,
-            Byte status,
-            String sort,
-            String order,
-            Integer pageIndex,
-            Integer pageSize,
-            String labels
-    );
-
-    /**
-     * Add a new monitor
-     *
-     * @param monitor The monitor entity to create
-     * @param params List of parameters for the monitor
-     * @param collector Optional collector assignment
-     * @return The created monitor ID
-     */
-    Long addMonitor(Monitor monitor, List<Param> params, String collector);
-
-    /**
-     * Get all available monitor types with their display names
-     *
-     * @param language Language code (e.g., "en-US", "zh-CN")
-     * @return Map of monitor type key to display name
-     */
-    Map<String, String> getAvailableMonitorTypes(String language);
-
-    /**
-     * Get parameter definitions for a specific monitor type
-     *
-     * @param app Monitor type/application name (e.g., "linux", "mysql", "redis")
-     * @return List of parameter definitions for the monitor type
-     */
-    List<ParamDefine> getMonitorParamDefines(String app);
-}
-
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/AlertDefineServiceAdapterImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/AlertDefineServiceAdapterImpl.java
deleted file mode 100644
index a22093c62d..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/AlertDefineServiceAdapterImpl.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters.impl;
-
-import com.usthe.sureness.subject.SubjectSum;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.AlertDefineServiceAdapter;
-import org.apache.hertzbeat.ai.config.McpContextHolder;
-import org.apache.hertzbeat.ai.pojo.dto.Hierarchy;
-import org.apache.hertzbeat.ai.utils.UtilityClass;
-import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
-import org.apache.hertzbeat.common.support.SpringContextHolder;
-import org.springframework.data.domain.Page;
-import org.springframework.stereotype.Component;
-
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * Implementation of the AlertDefineServiceAdapter interface that provides access to alert definition information
- * through reflection by invoking the underlying alert define service implementation.
- */
-@Slf4j
-@Component
-public class AlertDefineServiceAdapterImpl implements AlertDefineServiceAdapter {
-
-    @Override
-    public AlertDefine addAlertDefine(AlertDefine alertDefine) {
-        try {
-            Object alertDefineService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for addAlertDefine: {}", subjectSum);
-
-            try {
-                alertDefineService = SpringContextHolder.getBean("alertDefineServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertDefineServiceImpl'");
-            }
-
-            assert alertDefineService != null;
-            log.debug("AlertDefineService bean found: {}", alertDefineService.getClass().getSimpleName());
-            
-            Method method = alertDefineService.getClass().getMethod("addAlertDefine", AlertDefine.class);
-
-            method.invoke(alertDefineService, alertDefine);
-            
-            log.debug("Successfully added alert define with ID: {}", alertDefine.getId());
-            return alertDefine;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: addAlertDefine", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke addAlertDefine via adapter", e);
-            throw new RuntimeException("Failed to invoke addAlertDefine via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public Page<AlertDefine> getAlertDefines(String search, String app, Boolean enabled, String sort, String order, int pageIndex, int pageSize) {
-        try {
-            Object alertDefineService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getAlertDefines: {}", subjectSum);
-
-            try {
-                alertDefineService = SpringContextHolder.getBean("alertDefineServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertDefineServiceImpl'");
-            }
-
-            assert alertDefineService != null;
-            log.debug("AlertDefineService bean found: {}", alertDefineService.getClass().getSimpleName());
-            
-            Method method = alertDefineService.getClass().getMethod(
-                    "getAlertDefines",
-                    List.class, String.class, String.class, String.class, int.class, int.class);
-
-            @SuppressWarnings("unchecked")
-            Page<AlertDefine> result = (Page<AlertDefine>) method.invoke(
-                    alertDefineService, null, search, sort, order, pageIndex, pageSize);
-            
-            log.debug("Successfully retrieved {} alert defines", result.getContent().size());
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getAlertDefines", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getAlertDefines via adapter", e);
-            throw new RuntimeException("Failed to invoke getAlertDefines via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public AlertDefine getAlertDefine(Long id) {
-        try {
-            Object alertDefineService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getAlertDefine: {}", subjectSum);
-
-            try {
-                alertDefineService = SpringContextHolder.getBean("alertDefineServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertDefineServiceImpl'");
-            }
-
-            assert alertDefineService != null;
-            log.debug("AlertDefineService bean found: {}", alertDefineService.getClass().getSimpleName());
-            
-            Method method = alertDefineService.getClass().getMethod("getAlertDefine", long.class);
-
-            AlertDefine result = (AlertDefine) method.invoke(alertDefineService, id);
-            
-            log.debug("Successfully retrieved alert define with ID: {}", id);
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getAlertDefine", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getAlertDefine via adapter for ID: {}", id, e);
-            throw new RuntimeException("Failed to invoke getAlertDefine via adapter: " + e.getMessage(), e);
-        }
-    }
-
-
-    @Override
-    public void toggleAlertDefineStatus(Long id, boolean enabled) {
-        try {
-            Object alertDefineService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for toggleAlertDefineStatus: {}", subjectSum);
-
-            try {
-                alertDefineService = SpringContextHolder.getBean("alertDefineServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertDefineServiceImpl'");
-            }
-
-            assert alertDefineService != null;
-            log.debug("AlertDefineService bean found: {}", alertDefineService.getClass().getSimpleName());
-            
-            // First get the existing AlertDefine
-            Method getMethod = alertDefineService.getClass().getMethod("getAlertDefine", long.class);
-            AlertDefine alertDefine = (AlertDefine) getMethod.invoke(alertDefineService, id);
-            
-            if (alertDefine == null) {
-                throw new RuntimeException("AlertDefine with ID " + id + " not found");
-            }
-            
-            // Update the enable status
-            alertDefine.setEnable(enabled);
-            
-            // Use modifyAlertDefine to save the changes
-            Method modifyMethod = alertDefineService.getClass().getMethod("modifyAlertDefine", AlertDefine.class);
-            modifyMethod.invoke(alertDefineService, alertDefine);
-            
-            log.debug("Successfully toggled alert define status for ID: {} to enabled: {}", id, enabled);
-
-        } catch (Exception e) {
-            log.error("Failed to invoke toggleAlertDefineStatus via adapter for ID: {}", id, e);
-            throw new RuntimeException("Failed to invoke toggleAlertDefineStatus via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public AlertDefine modifyAlertDefine(AlertDefine alertDefine) {
-        try {
-            Object alertDefineService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for modifyAlertDefine: {}", subjectSum);
-
-            try {
-                alertDefineService = SpringContextHolder.getBean("alertDefineServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertDefineServiceImpl'");
-            }
-
-            assert alertDefineService != null;
-            log.debug("AlertDefineService bean found: {}", alertDefineService.getClass().getSimpleName());
-            
-            Method method = alertDefineService.getClass().getMethod("modifyAlertDefine", AlertDefine.class);
-
-            method.invoke(alertDefineService, alertDefine);
-            
-            log.debug("Successfully modified alert define with ID: {}", alertDefine.getId());
-            return alertDefine;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: modifyAlertDefine", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke modifyAlertDefine via adapter", e);
-            throw new RuntimeException("Failed to invoke modifyAlertDefine via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    /**
-     * Retrieves the application hierarchy for a given app and language.
-     * Uses reflection to call the underlying app service method.
-     *
-     * @param app  The application name
-     * @param lang The language code (optional, defaults to "en-US")
-     * @return List of Hierarchy objects representing the app hierarchy
-     */
-
-    @Override
-    public List<Hierarchy> getAppHierarchy(String app, String lang) {
-        try {
-            Object appService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getAppHierarchy: {}", subjectSum);
-
-            try {
-                appService = SpringContextHolder.getBean("appServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'appServiceImpl', trying by class name");
-            }
-
-            assert appService != null;
-            log.debug("AppService bean found for getAppHierarchy: {}", appService.getClass().getSimpleName());
-
-            // Provide default language if not specified
-            if (lang == null || lang.trim().isEmpty()) {
-                lang = "en-US";
-            }
-
-            // Call getAppHierarchy method: getAppHierarchy(String app, String lang)
-            Method method = appService.getClass().getMethod("getAppHierarchy", String.class, String.class);
-
-            List<?> managerHierarchies = (List<?>) method.invoke(appService, app, lang);
-
-            // Convert manager DTOs to ai-agent DTOs
-            List<Hierarchy> result = UtilityClass.convertToAgentHierarchies(managerHierarchies);
-
-            log.debug("Successfully retrieved and converted {} hierarchies for app '{}'", result.size(), app);
-            return result;
-
-        } catch (Exception e) {
-            log.error("Failed to get app hierarchy for app '{}': {}", app, e.getMessage(), e);
-            throw new RuntimeException("Failed to get app hierarchy for " + app, e);
-        }
-    }
-
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/AlertServiceAdapterImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/AlertServiceAdapterImpl.java
deleted file mode 100644
index 8caf902f54..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/AlertServiceAdapterImpl.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters.impl;
-
-import com.usthe.sureness.subject.SubjectSum;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.AlertServiceAdapter;
-import org.apache.hertzbeat.ai.config.McpContextHolder;
-import org.apache.hertzbeat.alert.dto.AlertSummary;
-import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
-import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
-import org.apache.hertzbeat.common.support.SpringContextHolder;
-import org.springframework.data.domain.Page;
-import org.springframework.stereotype.Component;
-
-import java.lang.reflect.Method;
-
-/**
- * Implementation of the AlertServiceAdapter interface that provides access to alert information
- * through reflection by invoking the underlying alert service implementation.
- */
-@Slf4j
-@Component
-public class AlertServiceAdapterImpl implements AlertServiceAdapter {
-
-    @Override
-    public Page<SingleAlert> getSingleAlerts(String status, String search, String sort, String order, int pageIndex, int pageSize) {
-        try {
-            Object alertService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getSingleAlerts: {}", subjectSum);
-
-            try {
-                alertService = SpringContextHolder.getBean("alertServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertServiceImpl'");
-            }
-
-            assert alertService != null;
-            log.debug("AlertService bean found: {}", alertService.getClass().getSimpleName());
-            
-            Method method = alertService.getClass().getMethod(
-                    "getSingleAlerts",
-                    String.class, String.class, String.class, String.class, int.class, int.class);
-
-            @SuppressWarnings("unchecked")
-            Page<SingleAlert> result = (Page<SingleAlert>) method.invoke(
-                    alertService, status, search, sort, order, pageIndex, pageSize);
-            
-            log.debug("Successfully retrieved {} single alerts", result.getContent().size());
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getSingleAlerts", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getSingleAlerts via adapter", e);
-            throw new RuntimeException("Failed to invoke getSingleAlerts via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public Page<GroupAlert> getGroupAlerts(String status, String search, String sort, String order, int pageIndex, int pageSize) {
-        try {
-            Object alertService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getGroupAlerts: {}", subjectSum);
-
-            try {
-                alertService = SpringContextHolder.getBean("alertServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertServiceImpl'");
-            }
-
-            assert alertService != null;
-            log.debug("AlertService bean found: {}", alertService.getClass().getSimpleName());
-            
-            Method method = alertService.getClass().getMethod(
-                    "getGroupAlerts",
-                    String.class, String.class, String.class, String.class, int.class, int.class);
-
-            @SuppressWarnings("unchecked")
-            Page<GroupAlert> result = (Page<GroupAlert>) method.invoke(
-                    alertService, status, search, sort, order, pageIndex, pageSize);
-            
-            log.debug("Successfully retrieved {} group alerts", result.getContent().size());
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getGroupAlerts", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getGroupAlerts via adapter", e);
-            throw new RuntimeException("Failed to invoke getGroupAlerts via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public AlertSummary getAlertsSummary() {
-        try {
-            Object alertService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getAlertsSummary: {}", subjectSum);
-
-            try {
-                alertService = SpringContextHolder.getBean("alertServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'alertServiceImpl'");
-            }
-
-            assert alertService != null;
-            log.debug("AlertService bean found: {}", alertService.getClass().getSimpleName());
-            
-            Method method = alertService.getClass().getMethod("getAlertsSummary");
-
-            AlertSummary result = (AlertSummary) method.invoke(alertService);
-            
-            log.debug("Successfully retrieved alerts summary");
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getAlertsSummary", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getAlertsSummary via adapter", e);
-            throw new RuntimeException("Failed to invoke getAlertsSummary via adapter: " + e.getMessage(), e);
-        }
-    }
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/MetricsServiceAdapterImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/MetricsServiceAdapterImpl.java
deleted file mode 100644
index d225ba87fd..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/MetricsServiceAdapterImpl.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters.impl;
-
-import com.usthe.sureness.subject.SubjectSum;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.MetricsServiceAdapter;
-import org.apache.hertzbeat.ai.config.McpContextHolder;
-import org.apache.hertzbeat.common.entity.dto.MetricsData;
-import org.apache.hertzbeat.common.entity.dto.MetricsHistoryData;
-import org.apache.hertzbeat.common.support.SpringContextHolder;
-import org.springframework.stereotype.Component;
-
-import java.lang.reflect.Method;
-
-/**
- * Implementation of the MetricsServiceAdapter interface that provides access to metrics information
- * through reflection by invoking the underlying metrics service implementation.
- */
-@Slf4j
-@Component
-public class MetricsServiceAdapterImpl implements MetricsServiceAdapter {
-
-    @Override
-    public Boolean getWarehouseStorageServerStatus() {
-        try {
-            Object metricsDataService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getWarehouseStorageServerStatus: {}", subjectSum);
-
-            try {
-                metricsDataService = SpringContextHolder.getBean("metricsDataServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'metricsDataServiceImpl'");
-            }
-
-            assert metricsDataService != null;
-            log.debug("MetricsDataService bean found: {}", metricsDataService.getClass().getSimpleName());
-            
-            Method method = metricsDataService.getClass().getMethod("getWarehouseStorageServerStatus");
-
-            Boolean result = (Boolean) method.invoke(metricsDataService);
-            
-            log.debug("Successfully retrieved warehouse storage server status: {}", result);
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getWarehouseStorageServerStatus", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getWarehouseStorageServerStatus via adapter", e);
-            throw new RuntimeException("Failed to invoke getWarehouseStorageServerStatus via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public MetricsData getMetricsData(Long monitorId, String metrics) {
-        try {
-            Object metricsDataService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getMetricsData: {}", subjectSum);
-
-            try {
-                metricsDataService = SpringContextHolder.getBean("metricsDataServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'metricsDataServiceImpl'");
-            }
-
-            assert metricsDataService != null;
-            log.debug("MetricsDataService bean found: {}", metricsDataService.getClass().getSimpleName());
-            
-            Method method = metricsDataService.getClass().getMethod(
-                    "getMetricsData",
-                    Long.class, String.class);
-
-            MetricsData result = (MetricsData) method.invoke(metricsDataService, monitorId, metrics);
-            
-            log.debug("Successfully retrieved metrics data for monitor {} and metrics {}", monitorId, metrics);
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getMetricsData", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getMetricsData via adapter for monitor {} and metrics {}", monitorId, metrics, e);
-            throw new RuntimeException("Failed to invoke getMetricsData via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public MetricsHistoryData getMetricHistoryData(Long monitorId, String app, String metrics, String metric, String label, String history, Boolean interval) {
-        try {
-            Object metricsDataService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getMetricHistoryData: {}", subjectSum);
-
-            try {
-                metricsDataService = SpringContextHolder.getBean("metricsDataServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'metricsDataServiceImpl'");
-            }
-
-            assert metricsDataService != null;
-            log.debug("MetricsDataService bean found: {}", metricsDataService.getClass().getSimpleName());
-            
-            Method method = metricsDataService.getClass().getMethod(
-                    "getMetricHistoryData",
-                    Long.class, String.class, String.class, String.class, String.class, String.class, Boolean.class);
-
-            MetricsHistoryData result = (MetricsHistoryData) method.invoke(
-                    metricsDataService, monitorId, app, metrics, metric, label, history, interval);
-            
-            log.debug("Successfully retrieved historical metrics data for monitor {} and metrics {}", monitorId, metrics);
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getMetricHistoryData", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getMetricHistoryData via adapter for monitor {} and metrics {}", monitorId, metrics, e);
-            throw new RuntimeException("Failed to invoke getMetricHistoryData via adapter: " + e.getMessage(), e);
-        }
-    }
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/MonitorServiceAdapterImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/MonitorServiceAdapterImpl.java
deleted file mode 100644
index 8a4f381fca..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/adapters/impl/MonitorServiceAdapterImpl.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * 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.hertzbeat.ai.adapters.impl;
-
-import com.usthe.sureness.subject.SubjectSum;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.MonitorServiceAdapter;
-import org.apache.hertzbeat.ai.config.McpContextHolder;
-import org.springframework.data.domain.Page;
-import org.apache.hertzbeat.common.entity.manager.Monitor;
-import org.apache.hertzbeat.common.entity.manager.Param;
-import org.apache.hertzbeat.common.entity.manager.ParamDefine;
-import org.apache.hertzbeat.common.support.SpringContextHolder;
-import org.springframework.stereotype.Component;
-
-import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Implementation of the MonitorServiceAdapter interface that provides access to monitor information
- * through reflection by invoking the underlying monitor service implementation.
- */
-@Slf4j
-@Component
-public class MonitorServiceAdapterImpl implements MonitorServiceAdapter {
-
-    @Override
-    public Page<Monitor> getMonitors(
-            List<Long> ids,
-            String app,
-            String search,
-            Byte status,
-            String sort,
-            String order,
-            Integer pageIndex,
-            Integer pageSize,
-            String labels) {
-        try {
-            // Provide default values for all nullable parameters
-            if (sort == null || sort.trim().isEmpty()) {
-                sort = "gmtCreate";
-            }
-            if (order == null || order.trim().isEmpty()) {
-                order = "desc";
-            }
-            if (pageIndex == null) {
-                pageIndex = 0;
-            }
-            if (pageSize == null) {
-                pageSize = 8;
-            }
-
-            Object monitorService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject: {}", subjectSum);
-
-            try {
-                monitorService = SpringContextHolder.getBean("monitorServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'monitorServiceImpl', trying by class name");
-            }
-
-            assert monitorService != null;
-            log.debug("MonitorService bean found: {}", monitorService.getClass().getSimpleName());
-            Method method = monitorService.getClass().getMethod(
-                    "getMonitors",
-                    List.class, String.class, String.class, Byte.class,
-                    String.class, String.class, int.class, int.class, String.class);
-
-
-            @SuppressWarnings("unchecked")
-            Page<Monitor> result = (Page<Monitor>) method.invoke(
-                    monitorService,
-                    ids, app, search, status, sort, order, pageIndex, pageSize, labels);
-            log.debug("MonitorServiceAdapter.getMonitors result: {}", result.getContent());
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getMonitors", e);
-        } catch (Exception e) {
-            log.debug("Failed to invoke getMonitors via adapter", e);
-            throw new RuntimeException("Failed to invoke getMonitors via adapter", e);
-        }
-    }
-
-    @Override
-    public Long addMonitor(Monitor monitor, List<Param> params, String collector) {
-        try {
-            Object monitorService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for addMonitor: {}", subjectSum);
-
-            try {
-                monitorService = SpringContextHolder.getBean("monitorServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'monitorServiceImpl', trying by class name");
-            }
-
-            assert monitorService != null;
-            log.debug("MonitorService bean found for addMonitor: {}", monitorService.getClass().getSimpleName());
-
-            // Call addMonitor method: addMonitor(Monitor monitor, List<Param> params, String collector, GrafanaDashboard dashboard)
-            Method method = monitorService.getClass().getMethod(
-                    "addMonitor",
-                    Monitor.class, List.class, String.class,
-                    Class.forName("org.apache.hertzbeat.common.entity.grafana.GrafanaDashboard"));
-
-            // Call the method with null dashboard
-            method.invoke(monitorService, monitor, params, collector, null);
-
-            log.debug("Successfully added monitor: {} with ID: {}", monitor.getName(), monitor.getId());
-            return monitor.getId();
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: addMonitor", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke addMonitor via adapter", e);
-            throw new RuntimeException("Failed to invoke addMonitor via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public Map<String, String> getAvailableMonitorTypes(String language) {
-        try {
-            Object appService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getAvailableMonitorTypes: {}", subjectSum);
-
-            try {
-                appService = SpringContextHolder.getBean("appServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'appServiceImpl', trying by class name");
-            }
-
-            assert appService != null;
-            log.debug("AppService bean found for getAvailableMonitorTypes: {}", appService.getClass().getSimpleName());
-
-            // Provide default language if not specified
-            if (language == null || language.trim().isEmpty()) {
-                language = "en-US";
-            }
-
-            // Call getI18nApps method: getI18nApps(String lang)
-            Method method = appService.getClass().getMethod("getI18nApps", String.class);
-
-            @SuppressWarnings("unchecked")
-            Map<String, String> result = (Map<String, String>) method.invoke(appService, language);
-
-            log.debug("Successfully retrieved {} monitor types", result.size());
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getI18nApps", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getI18nApps via adapter", e);
-            throw new RuntimeException("Failed to invoke getI18nApps via adapter: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public List<ParamDefine> getMonitorParamDefines(String app) {
-        try {
-            Object appService = null;
-            SubjectSum subjectSum = McpContextHolder.getSubject();
-            log.debug("Current security subject for getMonitorParamDefines: {}", subjectSum);
-
-            try {
-                appService = SpringContextHolder.getBean("appServiceImpl");
-            } catch (Exception e) {
-                log.debug("Could not find bean by name 'appServiceImpl', trying by class name");
-            }
-
-            assert appService != null;
-            log.debug("AppService bean found for getMonitorParamDefines: {}", appService.getClass().getSimpleName());
-
-            // Validate app parameter
-            if (app == null || app.trim().isEmpty()) {
-                throw new IllegalArgumentException("Monitor type/app parameter is required");
-            }
-
-            // Call getAppParamDefines method: getAppParamDefines(String app)
-            Method method = appService.getClass().getMethod("getAppParamDefines", String.class);
-
-            @SuppressWarnings("unchecked")
-            List<ParamDefine> result = (List<ParamDefine>) method.invoke(appService, app.toLowerCase().trim());
-
-            log.debug("Successfully retrieved {} parameter definitions for monitor type: {}", result.size(), app);
-            return result;
-
-        } catch (NoSuchMethodException e) {
-            throw new RuntimeException("Method not found: getAppParamDefines", e);
-        } catch (Exception e) {
-            log.error("Failed to invoke getAppParamDefines via adapter for app: {}", app, e);
-            throw new RuntimeException("Failed to invoke getAppParamDefines via adapter: " + e.getMessage(), e);
-        }
-    }
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/config/DynamicOpenAiApiKey.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/config/DynamicOpenAiApiKey.java
deleted file mode 100644
index 3750db9ddc..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/config/DynamicOpenAiApiKey.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.hertzbeat.ai.config;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.pojo.dto.ModelProviderConfig;
-import org.apache.hertzbeat.base.dao.GeneralConfigDao;
-import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
-import org.apache.hertzbeat.common.util.JsonUtil;
-import org.jetbrains.annotations.NotNull;
-import org.springframework.ai.model.ApiKey;
-import org.springframework.stereotype.Component;
-
-/**
- * Dynamic LLM Provider API Key implementation that retrieves the API key
- */
-@Slf4j
-@Component
-public class DynamicOpenAiApiKey implements ApiKey {
-
-    private final GeneralConfigDao generalConfigDao;
-    
-    public DynamicOpenAiApiKey(GeneralConfigDao generalConfigDao) {
-        this.generalConfigDao = generalConfigDao;
-    }
-
-    @NotNull
-    @Override
-    public String getValue() {
-        GeneralConfig providerConfig = generalConfigDao.findByType("provider");
-        ModelProviderConfig modelProviderConfig = JsonUtil.fromJson(providerConfig.getContent(), ModelProviderConfig.class);
-
-        if (modelProviderConfig != null && modelProviderConfig.isEnable() && modelProviderConfig.isStatus()) {
-            log.debug("Retrieved {} API key from configuration service", modelProviderConfig.getCode());
-            return modelProviderConfig.getApiKey();
-        } else {
-            log.warn("No valid LLM Provider API key found in configuration");
-            return "";
-        }
-    }
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/config/LlmConfig.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/config/LlmConfig.java
index 60a6db740a..b145344610 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/config/LlmConfig.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/config/LlmConfig.java
@@ -20,7 +20,7 @@ package org.apache.hertzbeat.ai.config;
 
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.common.support.event.AiProviderConfigChangeEvent;
-import org.apache.hertzbeat.ai.pojo.dto.ModelProviderConfig;
+import org.apache.hertzbeat.common.entity.dto.ModelProviderConfig;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
 import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
 import org.apache.hertzbeat.common.util.JsonUtil;
@@ -72,12 +72,7 @@ public class LlmConfig {
         }
         ModelProviderConfig modelProviderConfig = JsonUtil.fromJson(providerConfig.getContent(), ModelProviderConfig.class);
 
-        if (!modelProviderConfig.isEnable() || !modelProviderConfig.isStatus()) {
-            log.warn("LLM Provider is not enabled or status is not valid, ChatClient bean will not be created");
-            return null;
-        }
-
-        if (modelProviderConfig.getApiKey() == null) {
+        if (modelProviderConfig == null || modelProviderConfig.getApiKey() == null) {
             log.warn("LLM Provider configuration is incomplete, ChatClient bean will not be created");
             return null;
         }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/controller/ChatController.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/controller/ChatController.java
index dea6ffe6b3..71c5d47cb5 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/controller/ChatController.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/controller/ChatController.java
@@ -25,9 +25,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.ai.config.McpContextHolder;
 import org.apache.hertzbeat.ai.pojo.dto.ChatRequestContext;
-import org.apache.hertzbeat.ai.pojo.dto.ChatResponseDto;
-import org.apache.hertzbeat.ai.pojo.dto.ConversationDto;
+import org.apache.hertzbeat.ai.pojo.dto.ChatResponseChunk;
 import org.apache.hertzbeat.ai.service.ConversationService;
+import org.apache.hertzbeat.common.entity.ai.ChatConversation;
 import org.apache.hertzbeat.common.entity.dto.Message;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
@@ -63,23 +63,6 @@ public class ChatController {
         this.conversationService = conversationService;
     }
 
-    /**
-     * Create a new conversation
-     *
-     * @return Created conversation details
-     */
-    @PostMapping(path = "/conversations")
-    @Operation(summary = "Create a new conversation", description = "Create a new conversation")
-    public ResponseEntity<Message<ConversationDto>> createConversation() {
-        try {
-            ConversationDto conversation = conversationService.createConversation();
-            return ResponseEntity.ok(Message.success(conversation));
-        } catch (Exception e) {
-            log.error("Error creating conversation: ", e);
-            return ResponseEntity.ok(Message.fail((byte) -1, "Failed to create conversation"));
-        }
-    }
-
     /**
      * Send a message and get a streaming response with conversation tracking
      *
@@ -88,14 +71,13 @@ public class ChatController {
      */
     @PostMapping(value = "/stream", produces = TEXT_EVENT_STREAM_VALUE)
     @Operation(summary = "Send a chat message with streaming response", description = "Send a message to AI and get a streaming response with conversation tracking")
-    public Flux<ServerSentEvent<ChatResponseDto>> streamChat(@Valid @RequestBody ChatRequestContext context) {
+    public Flux<ServerSentEvent<ChatResponseChunk>> streamChat(@Valid @RequestBody ChatRequestContext context) {
         try {
             // Validate message is not empty
             SubjectSum subject = SurenessContextHolder.getBindSubject();
-            log.info(subject.toString());
             McpContextHolder.setSubject(subject);
             if (context.getMessage() == null || context.getMessage().trim().isEmpty()) {
-                ChatResponseDto errorResponse = ChatResponseDto.builder()
+                ChatResponseChunk errorResponse = ChatResponseChunk.builder()
                         .conversationId(context.getConversationId())
                         .response("Error: Message cannot be empty")
                         .build();
@@ -109,7 +91,7 @@ public class ChatController {
 
         } catch (Exception e) {
             log.error("Error in stream chat endpoint: ", e);
-            ChatResponseDto errorResponse = ChatResponseDto.builder()
+            ChatResponseChunk errorResponse = ChatResponseChunk.builder()
                     .conversationId(context.getConversationId())
                     .response("An error occurred: " + e.getMessage())
                     .build();
@@ -119,6 +101,18 @@ public class ChatController {
         }
     }
 
+    /**
+     * Create a new conversation
+     *
+     * @return Created conversation details
+     */
+    @PostMapping(path = "/conversations")
+    @Operation(summary = "Create a new conversation", description = "Create a new conversation")
+    public ResponseEntity<Message<ChatConversation>> createConversation() {
+        ChatConversation conversation = conversationService.createConversation();
+        return ResponseEntity.ok(Message.success(conversation));
+    }
+
     /**
      * Get all conversations
      *
@@ -126,14 +120,9 @@ public class ChatController {
      */
     @GetMapping(path = "/conversations")
     @Operation(summary = "List all conversations", description = "Get a list of all conversations")
-    public ResponseEntity<Message<List<ConversationDto>>> listConversations() {
-        try {
-            List<ConversationDto> conversations = conversationService.getAllConversations();
-            return ResponseEntity.ok(Message.success(conversations));
-        } catch (Exception e) {
-            log.error("Error listing conversations: ", e);
-            return ResponseEntity.ok(Message.fail((byte) -1, "Failed to retrieve conversations"));
-        }
+    public ResponseEntity<Message<List<ChatConversation>>> listConversations() {
+        List<ChatConversation> conversations = conversationService.getAllConversations();
+        return ResponseEntity.ok(Message.success(conversations));
     }
 
     /**
@@ -144,26 +133,10 @@ public class ChatController {
      */
     @GetMapping(path = "/conversations/{conversationId}")
     @Operation(summary = "Get conversation history", description = "Get detailed information and message history for a specific conversation")
-    public ResponseEntity<Message<ConversationDto>> getConversation(
-            @Parameter(description = "Conversation ID", example = "conv-12345678") @PathVariable("conversationId") String conversationId) {
-        try {
-            // Validate conversation ID
-            if (conversationId == null || conversationId.trim().isEmpty()) {
-                return ResponseEntity.ok(Message.fail((byte) -1, "Conversation ID is required"));
-            }
-
-            ConversationDto conversation = conversationService.getConversation(conversationId);
-
-            if (conversation == null) {
-                return ResponseEntity.ok(Message.fail((byte) -1, "Conversation not found: " + conversationId));
-            }
-
-            return ResponseEntity.ok(Message.success(conversation));
-
-        } catch (Exception e) {
-            log.error("Error getting conversation: ", e);
-            return ResponseEntity.ok(Message.fail((byte) -1, "Failed to retrieve conversation"));
-        }
+    public ResponseEntity<Message<ChatConversation>> getConversation(
+            @Parameter(description = "Conversation ID", example = "12345678") @PathVariable(value = "conversationId") Long conversationId) {
+        ChatConversation conversation = conversationService.getConversation(conversationId);
+        return ResponseEntity.ok(Message.success(conversation));
     }
 
     /**
@@ -175,23 +148,8 @@ public class ChatController {
     @DeleteMapping(path = "/conversations/{conversationId}")
     @Operation(summary = "Delete conversation", description = "Delete a specific conversation and all its messages")
     public ResponseEntity<Message<Void>> deleteConversation(
-            @Parameter(description = "Conversation ID", example = "conv-12345678") @PathVariable("conversationId") String conversationId) {
-        try {
-            // Validate conversation ID
-            if (conversationId == null || conversationId.trim().isEmpty()) {
-                return ResponseEntity.ok(Message.fail((byte) -1, "Conversation ID is required"));
-            }
-
-            boolean deleted = conversationService.deleteConversation(conversationId);
-            if (!deleted) {
-                return ResponseEntity.ok(Message.fail((byte) -1, "Conversation not found: " + conversationId));
-            }
-
-            return ResponseEntity.ok(Message.success("Conversation deleted successfully"));
-        } catch (Exception e) {
-            log.error("Error deleting conversation: ", e);
-            return ResponseEntity.ok(Message.fail((byte) -1, "Failed to delete conversation"));
-        }
-
+            @Parameter(description = "Conversation ID", example = "2345678") @PathVariable("conversationId") Long conversationId) {
+        conversationService.deleteConversation(conversationId);
+        return ResponseEntity.ok(Message.success());
     }
 }
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/AlibabaAiServiceTest.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/dao/ChatConversationDao.java
similarity index 69%
rename from hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/AlibabaAiServiceTest.java
rename to hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/dao/ChatConversationDao.java
index ff0a5b0f33..971b51f7cb 100644
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/AlibabaAiServiceTest.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/dao/ChatConversationDao.java
@@ -15,13 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.manager.service;
+package org.apache.hertzbeat.ai.dao;
 
-import org.apache.hertzbeat.manager.service.ai.AlibabaAiServiceImpl;
+import org.apache.hertzbeat.common.entity.ai.ChatConversation;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
 
 /**
- * test case for {@link AlibabaAiServiceImpl}
+ * Repository interface for Conversation entities
  */
-
-class AlibabaAiServiceTest {
+@Repository
+public interface ChatConversationDao extends JpaRepository<ChatConversation, Long> {
 }
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/SparkDeskAiServiceTest.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/dao/ChatMessageDao.java
similarity index 70%
rename from hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/SparkDeskAiServiceTest.java
rename to hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/dao/ChatMessageDao.java
index 47d281bd77..e70b09e812 100644
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/SparkDeskAiServiceTest.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/dao/ChatMessageDao.java
@@ -15,13 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.manager.service;
+package org.apache.hertzbeat.ai.dao;
 
-import org.apache.hertzbeat.manager.service.ai.SparkDeskAiServiceImpl;
+import org.apache.hertzbeat.common.entity.ai.ChatMessage;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
 
 /**
- * test case for {@link SparkDeskAiServiceImpl}
+ * Repository interface for Message entities
  */
-
-class SparkDeskAiServiceTest {
+@Repository
+public interface ChatMessageDao extends JpaRepository<ChatMessage, Long> {
+    
 }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatRequestContext.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatRequestContext.java
index 0ca317d9b9..d0dcfacf06 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatRequestContext.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatRequestContext.java
@@ -24,6 +24,7 @@ import lombok.Data;
 import lombok.NoArgsConstructor;
 
 import java.util.List;
+import org.apache.hertzbeat.common.entity.ai.ChatMessage;
 
 /**
  * Chat request context for AI chat endpoint.
@@ -40,10 +41,10 @@ public class ChatRequestContext {
     /**
      * Optional conversation ID for context
      */
-    private String conversationId;
+    private Long conversationId;
 
     /**
      * Conversation history messages for context
      */
-    private List<MessageDto> conversationHistory;
+    private List<ChatMessage> conversationHistory;
 }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatResponseDto.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatResponseChunk.java
similarity index 78%
rename from hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatResponseDto.java
rename to hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatResponseChunk.java
index 1e154d2534..0fd3ee68d8 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatResponseDto.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ChatResponseChunk.java
@@ -31,17 +31,18 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 @AllArgsConstructor
 @Schema(description = "Chat response")
-public class ChatResponseDto {
+public class ChatResponseChunk {
 
-    @Schema(description = "Conversation ID", example = "conv-123")
-    private String conversationId;
+    @Schema(description = "Conversation ID", example = "123")
+    private Long conversationId;
 
     @Schema(description = "AI response message", example = "Here are your monitors...")
     private String response;
 
-    @Schema(description = "User message ID", example = "msg-user-123")
-    private String userMessageId;
+    @Schema(description = "User message ID", example = "123")
+    private Long userMessageId;
+    
+    @Schema(description = "Assistant message ID", example = "123")
+    private Long assistantMessageId;
 
-    @Schema(description = "Assistant message ID", example = "msg-assistant-123")
-    private String assistantMessageId;
 }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ConversationDto.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ConversationDto.java
deleted file mode 100644
index 9b54af5253..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ConversationDto.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.hertzbeat.ai.pojo.dto;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-/**
- * Conversation DTO for AI chat conversations.
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@Schema(description = "Conversation information")
-public class ConversationDto {
-
-    @Schema(description = "Conversation ID", example = "conv-123")
-    private String conversationId;
-
-    @Schema(description = "Creation time")
-    private LocalDateTime createdAt;
-
-    @Schema(description = "Last updated time")
-    private LocalDateTime updatedAt;
-
-    @Schema(description = "Messages in this conversation")
-    private List<MessageDto> messages;
-
-    @Schema(description = "Message count")
-    private Integer messageCount;
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/Hierarchy.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/Hierarchy.java
deleted file mode 100644
index 2d750fe52b..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/Hierarchy.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.hertzbeat.ai.pojo.dto;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-
-import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
-
-/**
- * Hierarchical structure
- * eg: Monitoring Type metrics Information Hierarchy Relationship
- */
-@AllArgsConstructor
-@NoArgsConstructor
-@Data
-@Schema(description = "Monitor Hierarchy")
-public class Hierarchy {
-
-    /**
-     * Category value
-     */
-    @Schema(description = "Category Value", example = "os", accessMode = READ_WRITE)
-    String category;
-
-    /**
-     * Attribute value
-     */
-    @Schema(description = "Attribute value", example = "linux", accessMode = READ_WRITE)
-    String value;
-
-    /**
-     * Attribute internationalization tag
-     */
-    @Schema(description = "Attribute internationalization tag", example = "Linux system", accessMode = READ_WRITE)
-    String label;
-
-    /**
-     * Is it a leaf node
-     */
-    @Schema(description = "Is it a leaf node", example = "true", accessMode = READ_WRITE)
-    Boolean isLeaf = false;
-
-    /**
-     * Is hide this app type in main menus layout
-     */
-    @Schema(description = "Is hide this app in main menus layout, only for app type, default true.", example = "true")
-    Boolean hide = true;
-    
-    /**
-     * For leaf metric
-     * metric type 0-number: number 1-string: string
-     */
-    @Schema(description = "metric type 0-number: number 1-string: string")
-    private Byte type;
-    
-    /**
-     * metric unit
-     */
-    @Schema(description = "metric unit")
-    private String unit;
-
-    /**
-     * Next level of association
-     */
-    @Schema(description = "Next Hierarchy", accessMode = READ_WRITE)
-    private List<Hierarchy> children;
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/MessageDto.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/MessageDto.java
deleted file mode 100644
index 857b31aeff..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/MessageDto.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.hertzbeat.ai.pojo.dto;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * Message DTO for chat messages.
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-@Schema(description = "Chat message")
-public class MessageDto {
-
-    @Schema(description = "Message ID", example = "msg-123")
-    private String messageId;
-
-    @Schema(description = "Conversation ID", example = "conv-123")
-    private String conversationId;
-
-    @Schema(description = "Message content", example = "List all monitors")
-    private String content;
-
-    @Schema(description = "Message role", example = "user", allowableValues = {"user", "assistant"})
-    private String role;
-
-    @Schema(description = "Message timestamp")
-    private LocalDateTime timestamp;
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/AiConfigService.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/AiConfigService.java
deleted file mode 100644
index 03134f7a89..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/AiConfigService.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.hertzbeat.ai.service;
-
-/**
- * Ai Configuration Service
- */
-public interface AiConfigService {
-
-    /**
-     * Validate OpenAI API key by calling the OpenAI API
-     * @param apiKey the API key to validate
-     * @return validation result with success status and message
-     */
-    ValidationResult validateApiKey(String apiKey);
-
-    /**
-     * Validation result class
-     */
-    class ValidationResult {
-        private final boolean valid;
-        private final String message;
-
-        private ValidationResult(boolean valid, String message) {
-            this.valid = valid;
-            this.message = message;
-        }
-
-        public static ValidationResult success(String message) {
-            return new ValidationResult(true, message);
-        }
-
-        public static ValidationResult failure(String message) {
-            return new ValidationResult(false, message);
-        }
-
-        public boolean isValid() {
-            return valid;
-        }
-
-        public String getMessage() {
-            return message;
-        }
-    }
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/ConversationService.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/ConversationService.java
index a33a044eb0..a9eadef052 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/ConversationService.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/ConversationService.java
@@ -18,8 +18,8 @@
 
 package org.apache.hertzbeat.ai.service;
 
-import org.apache.hertzbeat.ai.pojo.dto.ChatResponseDto;
-import org.apache.hertzbeat.ai.pojo.dto.ConversationDto;
+import org.apache.hertzbeat.ai.pojo.dto.ChatResponseChunk;
+import org.apache.hertzbeat.common.entity.ai.ChatConversation;
 import org.springframework.http.codec.ServerSentEvent;
 import reactor.core.publisher.Flux;
 
@@ -30,13 +30,6 @@ import java.util.List;
  */
 public interface ConversationService {
 
-    /**
-     * Create a new conversation
-     *
-     * @return Created conversation data
-     */
-    ConversationDto createConversation();
-
     /**
      * Send a message and receive a streaming response
      *
@@ -44,8 +37,14 @@ public interface ConversationService {
      * @param conversationId Optional conversation ID for continuing a chat
      * @return Flux of ServerSentEvent for streaming the response
      */
-    Flux<ServerSentEvent<ChatResponseDto>> streamChat(String message, String conversationId);
+    Flux<ServerSentEvent<ChatResponseChunk>> streamChat(String message, Long conversationId);
 
+    /**
+     * Create a new conversation
+     *
+     * @return Created conversation data
+     */
+    ChatConversation createConversation();
 
     /**
      * Get conversation history for a specific conversation
@@ -53,28 +52,19 @@ public interface ConversationService {
      * @param conversationId Conversation ID
      * @return Conversation data including messages
      */
-    ConversationDto getConversation(String conversationId);
+    ChatConversation getConversation(Long conversationId);
 
     /**
      * Get all conversations for the current user
      *
      * @return List of conversations
      */
-    List<ConversationDto> getAllConversations();
+    List<ChatConversation> getAllConversations();
 
     /**
      * Delete a conversation
      *
      * @param conversationId Conversation ID to delete
-     * @return true if deleted, false if conversation not found
-     */
-    boolean deleteConversation(String conversationId);
-
-    /**
-     * Check if a conversation exists
-     *
-     * @param conversationId Conversation ID to check
-     * @return true if conversation exists, false otherwise
      */
-    boolean conversationExists(String conversationId);
+    void deleteConversation(Long conversationId);
 }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/AiConfigServiceImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/AiConfigServiceImpl.java
deleted file mode 100644
index 17cb772fe9..0000000000
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/AiConfigServiceImpl.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.hertzbeat.ai.service.impl;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.service.AiConfigService;
-import org.apache.hertzbeat.base.dao.GeneralConfigDao;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Service;
-import org.springframework.util.StringUtils;
-import org.springframework.web.client.RestTemplate;
-
-/**
- * Ai Configuration Service Implementation
- */
-@Slf4j
-@Service
-public class AiConfigServiceImpl implements AiConfigService {
-    
-    private static final String OPENAI_MODELS_ENDPOINT = "https://api.openai.com/v1/models";
-    private final RestTemplate restTemplate;
-
-    private final GeneralConfigDao generalConfigDao;
-
-    public AiConfigServiceImpl(GeneralConfigDao generalConfigDao, RestTemplate restTemplate) {
-        this.restTemplate = restTemplate;
-        this.generalConfigDao = generalConfigDao;
-    }
-
-    @Override
-    public ValidationResult validateApiKey(String apiKey) {
-        if (!StringUtils.hasText(apiKey)) {
-            return ValidationResult.failure("API key cannot be empty");
-        }
-
-        if (!apiKey.startsWith("sk-")) {
-            return ValidationResult.failure("Invalid API key format. OpenAI API keys should start with 'sk-'");
-        }
-
-        try {
-            HttpHeaders headers = new HttpHeaders();
-            headers.set("Authorization", "Bearer " + apiKey);
-            headers.set("Content-Type", "application/json");
-            
-            HttpEntity<String> entity = new HttpEntity<>(headers);
-            
-            log.debug("Validating OpenAI API key by calling models endpoint");
-            ResponseEntity<String> response = restTemplate.exchange(
-                OPENAI_MODELS_ENDPOINT,
-                HttpMethod.GET,
-                entity,
-                String.class
-            );
-
-            if (response.getStatusCode() == HttpStatus.OK) {
-                log.info("OpenAI API key validation successful");
-                return ValidationResult.success("API key is valid");
-            } else {
-                log.warn("OpenAI API key validation failed with status: {}", response.getStatusCode());
-                return ValidationResult.failure("API key validation failed: " + response.getStatusCode());
-            }
-
-        } catch (Exception e) {
-            log.error("Error validating OpenAI API key", e);
-            String errorMessage = e.getMessage();
-            
-            // Parse common error messages
-            if (errorMessage.contains("401")) {
-                return ValidationResult.failure("Invalid API key - authentication failed");
-            } else if (errorMessage.contains("403")) {
-                return ValidationResult.failure("API key does not have permission to access models");
-            } else if (errorMessage.contains("429")) {
-                return ValidationResult.failure("Rate limit exceeded - please try again later");
-            } else if (errorMessage.contains("timeout") || errorMessage.contains("connect")) {
-                return ValidationResult.failure("Network error - unable to connect to OpenAI API");
-            } else {
-                return ValidationResult.failure("API key validation failed: " + errorMessage);
-            }
-        }
-    }
-}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java
index 565740711b..38e49c3a35 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ChatClientProviderServiceImpl.java
@@ -20,8 +20,8 @@ package org.apache.hertzbeat.ai.service.impl;
 
 import lombok.extern.slf4j.Slf4j;
 import org.apache.hertzbeat.ai.config.PromptProvider;
-import org.apache.hertzbeat.ai.pojo.dto.MessageDto;
-import org.apache.hertzbeat.ai.pojo.dto.ModelProviderConfig;
+import org.apache.hertzbeat.common.entity.ai.ChatMessage;
+import org.apache.hertzbeat.common.entity.dto.ModelProviderConfig;
 import org.apache.hertzbeat.ai.service.ChatClientProviderService;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
 import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
@@ -66,14 +66,6 @@ public class ChatClientProviderServiceImpl implements ChatClientProviderService
         this.generalConfigDao = generalConfigDao;
     }
 
-    public String complete(String message) {
-        ChatClient chatClient = applicationContext.getBean("openAiChatClient", ChatClient.class);
-        return chatClient.prompt()
-                .user(message)
-                .call()
-                .content();
-    }
-
     @Override
     public Flux<String> streamChat(ChatRequestContext context) {
         try {
@@ -84,7 +76,7 @@ public class ChatClientProviderServiceImpl implements ChatClientProviderService
 
             // Add conversation history if available
             if (context.getConversationHistory() != null && !context.getConversationHistory().isEmpty()) {
-                for (MessageDto historyMessage : context.getConversationHistory()) {
+                for (ChatMessage historyMessage : context.getConversationHistory()) {
                     if ("user".equals(historyMessage.getRole())) {
                         messages.add(new UserMessage(historyMessage.getContent()));
                     } else if ("assistant".equals(historyMessage.getRole())) {
@@ -117,7 +109,7 @@ public class ChatClientProviderServiceImpl implements ChatClientProviderService
         if (!isConfigured) {
             GeneralConfig providerConfig = generalConfigDao.findByType("provider");
             ModelProviderConfig modelProviderConfig = JsonUtil.fromJson(providerConfig.getContent(), ModelProviderConfig.class);
-            isConfigured = modelProviderConfig != null && modelProviderConfig.isStatus();   
+            isConfigured = modelProviderConfig != null && modelProviderConfig.getApiKey() != null;   
         }
         return isConfigured;
     }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ConversationServiceImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ConversationServiceImpl.java
index 9c3530768e..5a4416af62 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ConversationServiceImpl.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/service/impl/ConversationServiceImpl.java
@@ -18,25 +18,23 @@
 package org.apache.hertzbeat.ai.service.impl;
 
 import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.ai.dao.ChatConversationDao;
+import org.apache.hertzbeat.ai.dao.ChatMessageDao;
 import org.apache.hertzbeat.ai.pojo.dto.ChatRequestContext;
-import org.apache.hertzbeat.ai.pojo.dto.ChatResponseDto;
-import org.apache.hertzbeat.ai.pojo.dto.ConversationDto;
-import org.apache.hertzbeat.ai.pojo.dto.MessageDto;
+import org.apache.hertzbeat.ai.pojo.dto.ChatResponseChunk;
 import org.apache.hertzbeat.ai.service.ChatClientProviderService;
 import org.apache.hertzbeat.ai.service.ConversationService;
+import org.apache.hertzbeat.common.entity.ai.ChatConversation;
+import org.apache.hertzbeat.common.entity.ai.ChatMessage;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
 import org.springframework.http.codec.ServerSentEvent;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 import reactor.core.publisher.Flux;
 
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Collectors;
 
 /**
  * Implementation of the ConversationService interface for managing chat conversations.
@@ -44,35 +42,22 @@ import java.util.stream.Collectors;
 @Slf4j
 @Service
 public class ConversationServiceImpl implements ConversationService {
-
-    private final Map<String, Map<String, Object>> conversations = new ConcurrentHashMap<>();
-    private final Map<String, List<Map<String, Object>>> conversationMessages = new ConcurrentHashMap<>();
-
+    
     @Autowired
-    private ChatClientProviderService chatClientProviderService;
+    private ChatConversationDao conversationDao;
     
-    @Override
-    public ConversationDto createConversation() {
-        String conversationId = createNewConversation();
-        return getConversation(conversationId);
-    }
+    @Autowired
+    private ChatMessageDao messageDao;
+    
+    @Autowired
+    private ChatClientProviderService chatClientProviderService;
 
     @Override
-    public Flux<ServerSentEvent<ChatResponseDto>> streamChat(String message, String conversationId) {
-        // Validate conversation exists
-        if (!conversationExists(conversationId)) {
-            ChatResponseDto errorResponse = ChatResponseDto.builder()
-                    .conversationId(conversationId)
-                    .response("Error: Conversation not found: " + conversationId)
-                    .build();
-            return Flux.just(ServerSentEvent.builder(errorResponse)
-                    .event("error")
-                    .build());
-        }
+    public Flux<ServerSentEvent<ChatResponseChunk>> streamChat(String message, Long conversationId) {
 
-        // Check if OpenAI is properly configured
+        // Check if provider is properly configured
         if (!chatClientProviderService.isConfigured()) {
-            ChatResponseDto errorResponse = ChatResponseDto.builder()
+            ChatResponseChunk errorResponse = ChatResponseChunk.builder()
                     .conversationId(conversationId)
                     .response("Provider is not configured. Please configure your AI Provider.")
                     .build();
@@ -84,50 +69,50 @@ public class ConversationServiceImpl implements ConversationService {
         log.info("Starting streaming conversation: {}", conversationId);
 
         // Add user message to conversation
-        String userMessageId = addMessageToConversation(conversationId, message, "user");
-
-        // Get conversation history for context
-        List<Map<String, Object>> messagesList = conversationMessages.get(conversationId);
-        List<MessageDto> conversationHistory = new ArrayList<>();
-
-        if (messagesList != null && messagesList.size() > 1) {
-            // Get all messages except the last one (which is the current user message we just added)
-            for (int i = 0; i < messagesList.size() - 1; i++) {
-                Map<String, Object> msgMap = messagesList.get(i);
-                conversationHistory.add(mapToMessageDto(msgMap));
-            }
+        ChatMessage chatMessage = ChatMessage.builder().conversationId(conversationId)
+                .content(message).role("user").build();
+        chatMessage = messageDao.save(chatMessage);
+        ChatConversation conversation = conversationDao.getReferenceById(conversationId);
+        if (conversation.getTitle().startsWith("conversation")) {
+            // Auto-generate title from first user message
+            String title = message.length() > 30 ? message.substring(0, 27) + "..." : message;
+            conversation.setTitle(title);
+            conversationDao.save(conversation);
         }
 
         ChatRequestContext context = ChatRequestContext.builder()
                 .message(message)
                 .conversationId(conversationId)
-                .conversationHistory(conversationHistory)
+                .conversationHistory(CollectionUtils.isEmpty(conversation.getMessages()) ? null 
+                        : conversation.getMessages().subList(0, conversation.getMessages().size() - 1))
                 .build();
 
         // Stream response from AI service
         StringBuilder fullResponse = new StringBuilder();
+        ChatMessage finalChatMessage = chatMessage;
         return chatClientProviderService.streamChat(context)
                 .map(chunk -> {
                     fullResponse.append(chunk);
-                    ChatResponseDto responseDto = ChatResponseDto.builder()
+                    ChatResponseChunk responseChunk = ChatResponseChunk.builder()
                             .conversationId(conversationId)
+                            .userMessageId(finalChatMessage.getId())
                             .response(chunk)
-                            .userMessageId(userMessageId)
                             .build();
 
-                    return ServerSentEvent.builder(responseDto)
+                    return ServerSentEvent.builder(responseChunk)
                             .event("message")
                             .build();
                 })
                 .concatWith(Flux.defer(() -> {
                     // Add the complete AI response to conversation
-                    String assistantMessageId = addMessageToConversation(conversationId, fullResponse.toString(), "assistant");
-
-                    ChatResponseDto finalResponse = ChatResponseDto.builder()
+                    ChatMessage assistantMessage = ChatMessage.builder().conversationId(conversationId)
+                            .content(fullResponse.toString()).role("assistant").build();
+                    assistantMessage = messageDao.save(assistantMessage);
+                    
+                    ChatResponseChunk finalResponse = ChatResponseChunk.builder()
                             .conversationId(conversationId)
                             .response("")
-                            .userMessageId(userMessageId)
-                            .assistantMessageId(assistantMessageId)
+                            .assistantMessageId(assistantMessage.getId())
                             .build();
 
                     return Flux.just(ServerSentEvent.builder(finalResponse)
@@ -137,10 +122,10 @@ public class ConversationServiceImpl implements ConversationService {
                 .doOnComplete(() -> log.info("Streaming completed for conversation: {}", conversationId))
                 .doOnError(error -> log.error("Error in streaming chat for conversation {}: {}", conversationId, error.getMessage(), error))
                 .onErrorResume(error -> {
-                    ChatResponseDto errorResponse = ChatResponseDto.builder()
+                    ChatResponseChunk errorResponse = ChatResponseChunk.builder()
                             .conversationId(conversationId)
                             .response("An error occurred: " + error.getMessage())
-                            .userMessageId(userMessageId)
+                            .userMessageId(finalChatMessage.getId())
                             .build();
                     return Flux.just(ServerSentEvent.builder(errorResponse)
                             .event("error")
@@ -149,124 +134,27 @@ public class ConversationServiceImpl implements ConversationService {
     }
 
     @Override
-    public ConversationDto getConversation(String conversationId) {
-        if (conversationId == null || conversationId.isEmpty()) {
-            return null;
-        }
-
-        Map<String, Object> conversation = conversations.get(conversationId);
-        if (conversation == null) {
-            return null;
-        }
-
-        List<Map<String, Object>> messagesList = conversationMessages.get(conversationId);
-        List<MessageDto> messages = messagesList != null
-                ? messagesList.stream().map(this::mapToMessageDto).collect(Collectors.toList()) :
-                new ArrayList<>();
-
-        return ConversationDto.builder()
-                .conversationId((String) conversation.get("conversationId"))
-                .createdAt((LocalDateTime) conversation.get("createdAt"))
-                .updatedAt((LocalDateTime) conversation.get("updatedAt"))
-                .messages(messages)
-                .build();
+    public ChatConversation createConversation() {
+        ChatConversation conversation = new ChatConversation();
+        conversation.setTitle("conversation-" + UUID.randomUUID().toString().substring(0, 4));
+        return conversationDao.save(conversation);
     }
 
     @Override
-    public List<ConversationDto> getAllConversations() {
-        List<ConversationDto> result = new ArrayList<>();
-
-        for (Map.Entry<String, Map<String, Object>> entry : conversations.entrySet()) {
-            Map<String, Object> conv = entry.getValue();
-            List<Map<String, Object>> messages = conversationMessages.get(entry.getKey());
-
-            ConversationDto dto = ConversationDto.builder()
-                    .conversationId((String) conv.get("conversationId"))
-                    .createdAt((LocalDateTime) conv.get("createdAt"))
-                    .updatedAt((LocalDateTime) conv.get("updatedAt"))
-                    .messages(new ArrayList<>()) // Don't include messages in list view for performance
-                    .build();
-            result.add(dto);
+    public ChatConversation getConversation(Long conversationId) {
+        if (conversationId == null) {
+            return null;
         }
-
-        result.sort((a, b) -> b.getUpdatedAt().compareTo(a.getUpdatedAt()));
-
-        return result;
+        return conversationDao.getReferenceById(conversationId);
     }
 
     @Override
-    public boolean deleteConversation(String conversationId) {
-        if (conversationId == null || conversationId.isEmpty()) {
-            return false;
-        }
-
-        boolean existed = conversations.containsKey(conversationId);
-        if (existed) {
-            conversations.remove(conversationId);
-            conversationMessages.remove(conversationId);
-            log.info("Deleted conversation: {}", conversationId);
-        }
-        return existed;
+    public List<ChatConversation> getAllConversations() {
+        return conversationDao.findAll(Sort.by(Sort.Direction.DESC, "id"));
     }
 
     @Override
-    public boolean conversationExists(String conversationId) {
-        return conversationId != null && !conversationId.isEmpty() && conversations.containsKey(conversationId);
-    }
-
-    private String createNewConversation() {
-        String conversationId = "conv-" + UUID.randomUUID().toString().substring(0, 8);
-        LocalDateTime now = LocalDateTime.now();
-
-        Map<String, Object> conversation = new HashMap<>();
-        conversation.put("conversationId", conversationId);
-        conversation.put("createdAt", now);
-        conversation.put("updatedAt", now);
-
-        conversations.put(conversationId, conversation);
-        conversationMessages.put(conversationId, new ArrayList<>());
-
-        log.info("Created new conversation: {}", conversationId);
-        return conversationId;
+    public void deleteConversation(Long conversationId) {
+        conversationDao.deleteById(conversationId);
     }
-
-    private MessageDto mapToMessageDto(Map<String, Object> messageMap) {
-        return MessageDto.builder()
-                .messageId((String) messageMap.get("messageId"))
-                .conversationId((String) messageMap.get("conversationId"))
-                .content((String) messageMap.get("content"))
-                .role((String) messageMap.get("role"))
-                .timestamp((LocalDateTime) messageMap.get("timestamp"))
-                .build();
-    }
-
-    private String addMessageToConversation(String conversationId, String content, String role) {
-        List<Map<String, Object>> messages = conversationMessages.computeIfAbsent(conversationId, k -> new ArrayList<>());
-
-        String messageId = "msg-" + UUID.randomUUID().toString().substring(0, 8);
-        Map<String, Object> message = new HashMap<>();
-        message.put("messageId", messageId);
-        message.put("conversationId", conversationId);
-        message.put("content", content);
-        message.put("role", role);
-        message.put("timestamp", LocalDateTime.now());
-
-        messages.add(message);
-
-        // Update conversation timestamp
-        Map<String, Object> conversation = conversations.get(conversationId);
-        if (conversation != null) {
-            conversation.put("updatedAt", LocalDateTime.now());
-            // Auto-generate title from first user message
-            if ("user".equals(role) && messages.stream().filter(m -> "user".equals(m.get("role"))).count() == 1) {
-                String title = content.length() > 30 ? content.substring(0, 27) + "..." : content;
-                conversation.put("title", title);
-            }
-        }
-
-        return messageId;
-    }
-
-
-
 }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertDefineToolsImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertDefineToolsImpl.java
index 2fd8257b90..726617d815 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertDefineToolsImpl.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertDefineToolsImpl.java
@@ -22,12 +22,13 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.usthe.sureness.subject.SubjectSum;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.AlertDefineServiceAdapter;
-import org.apache.hertzbeat.ai.pojo.dto.Hierarchy;
 import org.apache.hertzbeat.ai.config.McpContextHolder;
+import org.apache.hertzbeat.alert.service.AlertDefineService;
+import org.apache.hertzbeat.manager.service.AppService;
 import org.apache.hertzbeat.ai.tools.AlertDefineTools;
 import org.apache.hertzbeat.ai.utils.UtilityClass;
 import org.apache.hertzbeat.common.entity.alerter.AlertDefine;
+import org.apache.hertzbeat.manager.pojo.dto.Hierarchy;
 import org.springframework.ai.tool.annotation.Tool;
 import org.springframework.ai.tool.annotation.ToolParam;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,7 +47,9 @@ import java.util.Map;
 @Service
 public class AlertDefineToolsImpl implements AlertDefineTools {
     @Autowired
-    private AlertDefineServiceAdapter alertDefineServiceAdapter;
+    private AlertDefineService alertDefineService;
+    @Autowired
+    private AppService appService;
 
 
     @Override
@@ -240,17 +243,19 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
                     .datasource(datasource)
                     .enable(enable)
                     .build();
+            
+            log.debug("Current security subject for addAlertDefine: {}", subjectSum);
 
-            AlertDefine createdAlertDefine = alertDefineServiceAdapter.addAlertDefine(alertDefine);
+            alertDefineService.addAlertDefine(alertDefine);
 
             // Note: Monitor binding is handled separately via bind_monitors_to_alert_rule tool
             String bindingNote = String.format(" (Use bind_monitors_to_alert_rule tool to associate specific monitors)");
 
-            log.info("Successfully created alert rule '{}' with ID: {}", name, createdAlertDefine.getId());
+            log.info("Successfully created alert rule '{}' with ID: {}", name, alertDefine.getId());
             
             StringBuilder response = new StringBuilder();
             response.append(String.format("Successfully created %s alert rule '%s' with ID: %d\n", 
-                    type, name, createdAlertDefine.getId()));
+                    type, name, alertDefine.getId()));
             response.append(String.format("Expression: %s\n", expr));
             response.append(String.format("Priority: %d (%s)\n", priority, severityLabel));
             response.append(String.format("Trigger after: %d consecutive violations\n", times));
@@ -296,8 +301,11 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
                 pageSize = 10;
             }
 
-            Page<AlertDefine> result = alertDefineServiceAdapter.getAlertDefines(
-                    search, monitorType, enabled, "gmtCreate", "desc", pageIndex, pageSize);
+            SubjectSum subjectSum = McpContextHolder.getSubject();
+            log.debug("Current security subject for getAlertDefines: {}", subjectSum);
+
+            Page<AlertDefine> result = alertDefineService.getAlertDefines(null,
+                    search, "gmtCreate", "desc", pageIndex, pageSize);
 
             StringBuilder response = new StringBuilder();
             response.append("Found ").append(result.getContent().size())
@@ -345,7 +353,21 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
         try {
             log.info("Toggling alert rule ID: {} to enabled: {}", ruleId, enabled);
 
-            alertDefineServiceAdapter.toggleAlertDefineStatus(ruleId, enabled);
+            SubjectSum subjectSum = McpContextHolder.getSubject();
+            log.debug("Current security subject for toggleAlertDefineStatus: {}", subjectSum);
+
+            // First get the existing AlertDefine
+            AlertDefine alertDefine = alertDefineService.getAlertDefine(ruleId);
+
+            if (alertDefine == null) {
+                throw new RuntimeException("AlertDefine with ID " + ruleId + " not found");
+            }
+
+            // Update the enable status
+            alertDefine.setEnable(enabled);
+
+            // Use modifyAlertDefine to save the changes
+            alertDefineService.modifyAlertDefine(alertDefine);
 
             log.info("Successfully toggled alert rule ID: {} to enabled: {}", ruleId, enabled);
             return String.format("Successfully %s alert rule ID: %d",
@@ -369,7 +391,10 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
         try {
             log.info("Getting alert rule details for ID: {}", ruleId);
 
-            AlertDefine alertDefine = alertDefineServiceAdapter.getAlertDefine(ruleId);
+            SubjectSum subjectSum = McpContextHolder.getSubject();
+            log.debug("Current security subject for getAlertDefine: {}", subjectSum);
+
+            AlertDefine alertDefine = alertDefineService.getAlertDefine(ruleId);
             if (alertDefine == null) {
                 return "Alert rule with ID " + ruleId + " not found";
             }
@@ -441,7 +466,7 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
             log.debug("Current subject in get_apps_metrics_hierarchy tool: {}", subjectSum);
 
             List<Hierarchy> hierarchies;
-            hierarchies = alertDefineServiceAdapter.getAppHierarchy(app.trim().toLowerCase(), "en-US");
+            hierarchies = appService.getAppHierarchy(app.trim().toLowerCase(), "en-US");
 
 
             ObjectMapper mapper = new ObjectMapper();
@@ -459,10 +484,7 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
                 result.put("message", "No hierarchy data available");
             }
 
-            String jsonResult = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result);
-            log.info("Hierarchy JSON: {}", jsonResult);
-
-            return jsonResult;
+            return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(result);
 
         } catch (Exception e) {
             log.error("Failed to get apps metrics hierarchy: {}", e.getMessage(), e);
@@ -494,7 +516,9 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
             }
 
             // Get the existing alert rule
-            AlertDefine existingRule = alertDefineServiceAdapter.getAlertDefine(ruleId);
+            log.debug("Current security subject for getAlertDefine: {}", subjectSum);
+
+            AlertDefine existingRule = alertDefineService.getAlertDefine(ruleId);
             if (existingRule == null) {
                 return String.format("Error: Alert rule with ID %d not found", ruleId);
             }
@@ -571,7 +595,9 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
                 
                 // Update the alert rule
                 existingRule.setExpr(newExpr);
-                alertDefineServiceAdapter.modifyAlertDefine(existingRule);
+                log.debug("Current security subject for modifyAlertDefine: {}", subjectSum);
+
+                alertDefineService.modifyAlertDefine(existingRule);
                 
                 log.info("Successfully added monitors {} to existing bindings for alert rule ID: {}", validMonitorIds, ruleId);
                 return String.format("Successfully added %d new monitor(s) to alert rule ID %d.\nTotal bound monitors: %s\nUpdated expression: %s", 
@@ -608,7 +634,8 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
 
             // Update the alert rule
             existingRule.setExpr(newExpr);
-            alertDefineServiceAdapter.modifyAlertDefine(existingRule);
+
+            alertDefineService.modifyAlertDefine(existingRule);
 
             log.info("Successfully bound monitors {} to alert rule ID: {}", validMonitorIds, ruleId);
             return String.format("Successfully bound %d monitor(s) to alert rule ID %d.\nMonitor IDs: %s\nUpdated expression: %s", 
@@ -633,7 +660,10 @@ public class AlertDefineToolsImpl implements AlertDefineTools {
             log.debug("Validating hierarchy relationships: app={}, metrics={}, fieldConditions={}", app, metrics, fieldConditions);
 
             // Get hierarchy for the specified app
-            List<Hierarchy> hierarchies = alertDefineServiceAdapter.getAppHierarchy(app.toLowerCase(), "en-US");
+            SubjectSum subjectSum = McpContextHolder.getSubject();
+            log.debug("Current security subject for getAppHierarchy: {}", subjectSum);
+
+            List<Hierarchy> hierarchies = appService.getAppHierarchy(app.toLowerCase(), "en-US");
 
             if (hierarchies == null || hierarchies.isEmpty()) {
                 return String.format("Error: App '%s' not found in hierarchy. Please use list_monitor_types to get valid app names.", app);
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertToolsImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertToolsImpl.java
index 1768769996..ad1f978828 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertToolsImpl.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/AlertToolsImpl.java
@@ -20,11 +20,11 @@ package org.apache.hertzbeat.ai.tools.impl;
 
 import com.usthe.sureness.subject.SubjectSum;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.AlertServiceAdapter;
 import org.apache.hertzbeat.ai.config.McpContextHolder;
 import org.apache.hertzbeat.ai.tools.AlertTools;
 import org.apache.hertzbeat.ai.utils.UtilityClass;
 import org.apache.hertzbeat.alert.dto.AlertSummary;
+import org.apache.hertzbeat.alert.service.AlertService;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -41,7 +41,7 @@ import org.springframework.stereotype.Service;
 @Service
 public class AlertToolsImpl implements AlertTools {
     @Autowired
-    private AlertServiceAdapter alertServiceAdapter;
+    private AlertService alertService;
 
     @Override
     @Tool(name = "query_alerts", description = """
@@ -116,7 +116,7 @@ public class AlertToolsImpl implements AlertTools {
 
             // Handle different alert types
             if ("single".equalsIgnoreCase(alertType) || "both".equalsIgnoreCase(alertType)) {
-                Page<SingleAlert> singleResult = alertServiceAdapter.getSingleAlerts(status, search, sort, order, pageIndex, pageSize);
+                Page<SingleAlert> singleResult = alertService.getSingleAlerts(status, search, sort, order, pageIndex, pageSize);
                 
                 response.append("SINGLE ALERTS:\n");
                 response.append("Found ").append(singleResult.getContent().size()).append(" single alerts (Total: ").append(singleResult.getTotalElements()).append("):\n\n");
@@ -154,7 +154,7 @@ public class AlertToolsImpl implements AlertTools {
                     response.append("\n");
                 }
                 
-                Page<GroupAlert> groupResult = alertServiceAdapter.getGroupAlerts(status, search, sort, order, pageIndex, pageSize);
+                Page<GroupAlert> groupResult = alertService.getGroupAlerts(status, search, sort, order, pageIndex, pageSize);
                 
                 response.append("GROUP ALERTS:\n");
                 response.append("Found ").append(groupResult.getContent().size()).append(" group alerts (Total: ").append(groupResult.getTotalElements()).append("):\n\n");
@@ -205,7 +205,7 @@ public class AlertToolsImpl implements AlertTools {
             SubjectSum subjectSum = McpContextHolder.getSubject();
             log.debug("Current subject in get_alerts_summary tool: {}", subjectSum);
 
-            AlertSummary summary = alertServiceAdapter.getAlertsSummary();
+            AlertSummary summary = alertService.getAlertsSummary();
 
             StringBuilder response = new StringBuilder();
             response.append("ALERTS SUMMARY\n");
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MetricsToolsImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MetricsToolsImpl.java
index beb0cb1804..e5faa9c2c7 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MetricsToolsImpl.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MetricsToolsImpl.java
@@ -20,9 +20,8 @@ package org.apache.hertzbeat.ai.tools.impl;
 
 import com.usthe.sureness.subject.SubjectSum;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.MetricsServiceAdapter;
-import org.apache.hertzbeat.ai.adapters.MonitorServiceAdapter;
 import org.apache.hertzbeat.ai.config.McpContextHolder;
+import org.apache.hertzbeat.warehouse.service.MetricsDataService;
 import org.apache.hertzbeat.ai.tools.MetricsTools;
 import org.apache.hertzbeat.common.entity.dto.Field;
 import org.apache.hertzbeat.common.entity.dto.MetricsData;
@@ -44,9 +43,7 @@ import java.util.Map;
 @Service
 public class MetricsToolsImpl implements MetricsTools {
     @Autowired
-    private MetricsServiceAdapter metricsServiceAdapter;
-    @Autowired
-    private MonitorServiceAdapter monitorServiceAdapter;
+    private MetricsDataService metricsDataService;
 
     @Override
     @Tool(name = "query_realtime_metrics", description = """
@@ -78,7 +75,7 @@ public class MetricsToolsImpl implements MetricsTools {
             SubjectSum subjectSum = McpContextHolder.getSubject();
             log.debug("Current subject in get_realtime_metrics tool: {}", subjectSum);
 
-            MetricsData metricsData = metricsServiceAdapter.getMetricsData(monitorId, metrics);
+            MetricsData metricsData = metricsDataService.getMetricsData(monitorId, metrics);
 
             if (metricsData == null) {
                 return String.format("No real-time metrics data found for monitor ID %d and metrics '%s'", monitorId, metrics);
@@ -173,7 +170,7 @@ public class MetricsToolsImpl implements MetricsTools {
                 interval = true;
             }
 
-            MetricsHistoryData historyData = metricsServiceAdapter.getMetricHistoryData(
+            MetricsHistoryData historyData = metricsDataService.getMetricHistoryData(
                     monitorId, app, metrics, fieldParameter, label, history, interval);
 
             if (historyData == null) {
@@ -235,8 +232,10 @@ public class MetricsToolsImpl implements MetricsTools {
     public String getWarehouseStatus() {
         try {
             log.info("Checking warehouse storage status");
+            SubjectSum subjectSum = McpContextHolder.getSubject();
+            log.debug("Current security subject for getWarehouseStorageServerStatus: {}", subjectSum);
 
-            Boolean status = metricsServiceAdapter.getWarehouseStorageServerStatus();
+            Boolean status = metricsDataService.getWarehouseStorageServerStatus();
 
             StringBuilder response = new StringBuilder();
             response.append("METRICS WAREHOUSE STATUS\n");
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MonitorToolsImpl.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MonitorToolsImpl.java
index cd3a47962c..f0d2a1b6f7 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MonitorToolsImpl.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/tools/impl/MonitorToolsImpl.java
@@ -19,8 +19,9 @@ package org.apache.hertzbeat.ai.tools.impl;
 
 import com.usthe.sureness.subject.SubjectSum;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.adapters.MonitorServiceAdapter;
 import org.apache.hertzbeat.ai.config.McpContextHolder;
+import org.apache.hertzbeat.manager.service.MonitorService;
+import org.apache.hertzbeat.manager.service.AppService;
 import org.apache.hertzbeat.ai.utils.UtilityClass;
 import org.springframework.ai.tool.annotation.Tool;
 import org.springframework.data.domain.Page;
@@ -43,7 +44,9 @@ import java.util.Map;
 @Service
 public class MonitorToolsImpl implements MonitorTools {
     @Autowired
-    private MonitorServiceAdapter monitorServiceAdapter;
+    private MonitorService monitorService;
+    @Autowired
+    private AppService appService;
 
 
     /**
@@ -123,8 +126,12 @@ public class MonitorToolsImpl implements MonitorTools {
                 includeStats = false;
             }
             
-            Page<Monitor> result = monitorServiceAdapter.getMonitors(ids, app, search, status, sort, order, pageIndex, pageSize, labels);
-            log.debug("MonitorServiceAdapter.getMonitors result: {}", result);
+            SubjectSum subjectSum = McpContextHolder.getSubject();
+            log.debug("Current security subject: {}", subjectSum);
+
+            Page<Monitor> result = monitorService.getMonitors(
+                    ids, app, search, status, sort, order, pageIndex, pageSize, labels);
+            log.debug("MonitorService.getMonitors result: {}", result);
             
             StringBuilder response = new StringBuilder();
             response.append("MONITOR QUERY RESULTS\n");
@@ -133,10 +140,10 @@ public class MonitorToolsImpl implements MonitorTools {
             // Include statistics if requested
             if (includeStats) {
                 // Get status distribution by calling with different status values
-                long onlineCount = monitorServiceAdapter.getMonitors(null, app, search, (byte) 1, null, null, 0, 1000, labels).getTotalElements();
-                long offlineCount = monitorServiceAdapter.getMonitors(null, app, search, (byte) 2, null, null, 0, 1000, labels).getTotalElements();
-                long unreachableCount = monitorServiceAdapter.getMonitors(null, app, search, (byte) 3, null, null, 0, 1000, labels).getTotalElements();
-                long pausedCount = monitorServiceAdapter.getMonitors(null, app, search, (byte) 0, null, null, 0, 1000, labels).getTotalElements();
+                long onlineCount = monitorService.getMonitors(null, app, search, (byte) 1, null, null, 0, 1000, labels).getTotalElements();
+                long offlineCount = monitorService.getMonitors(null, app, search, (byte) 2, null, null, 0, 1000, labels).getTotalElements();
+                long unreachableCount = monitorService.getMonitors(null, app, search, (byte) 3, null, null, 0, 1000, labels).getTotalElements();
+                long pausedCount = monitorService.getMonitors(null, app, search, (byte) 0, null, null, 0, 1000, labels).getTotalElements();
                 
                 response.append("STATUS OVERVIEW:\n");
                 response.append("- Online: ").append(onlineCount).append("\n");
@@ -266,7 +273,10 @@ public class MonitorToolsImpl implements MonitorTools {
             
             // Validate that all required parameters for this monitor type are provided
             try {
-                List<ParamDefine> requiredParams = monitorServiceAdapter.getMonitorParamDefines(app);
+                SubjectSum subjectSum = McpContextHolder.getSubject();
+                log.debug("Current security subject for getMonitorParamDefines: {}", subjectSum);
+
+                List<ParamDefine> requiredParams = appService.getAppParamDefines(app.toLowerCase().trim());
                 log.info("Checking required parameters for monitor type '{}': {}", app, requiredParams);
                 List<String> missingParams = new ArrayList<>();
                 
@@ -290,8 +300,12 @@ public class MonitorToolsImpl implements MonitorTools {
                 log.warn("Could not validate required parameters for monitor type '{}': {}", app, e.getMessage());
             }
             
-            // Call adapter - it handles all the complexity (validation, defaults, app-specific logic)
-            Long monitorId = monitorServiceAdapter.addMonitor(monitor, params, null);
+            // Call monitor service - it handles all the complexity (validation, defaults, app-specific logic)
+            SubjectSum subjectSum = McpContextHolder.getSubject();
+            log.debug("Current security subject for addMonitor: {}", subjectSum);
+
+            monitorService.addMonitor(monitor, params, null, null);
+            Long monitorId = monitor.getId();
             
             log.info("Successfully added monitor '{}' with ID: {}", name, monitorId);
             return String.format("Successfully added %s monitor '%s' with ID: %d (Host: %s, Interval: %d seconds)", 
@@ -361,14 +375,14 @@ public class MonitorToolsImpl implements MonitorTools {
             log.info("Listing available monitor types for language: {}", language);
             SubjectSum subjectSum = McpContextHolder.getSubject();
             log.debug("Current subject in list_monitor_types tool: {}", subjectSum);
-            
+
             // Set default language if not provided
             if (language == null || language.trim().isEmpty()) {
                 language = "en-US";
             }
-            
-            // Get available monitor types from adapter
-            Map<String, String> monitorTypes = monitorServiceAdapter.getAvailableMonitorTypes(language);
+
+            // Get available monitor types from app service
+            Map<String, String> monitorTypes = appService.getI18nApps(language);
             
             if (monitorTypes == null || monitorTypes.isEmpty()) {
                 return "No monitor types are currently available.";
@@ -416,14 +430,14 @@ public class MonitorToolsImpl implements MonitorTools {
             log.info("Getting parameter definitions for monitor type: {}", app);
             SubjectSum subjectSum = McpContextHolder.getSubject();
             log.debug("Current subject in get_monitor_param_defines tool: {}", subjectSum);
-            
+
             // Validate required parameter
             if (app == null || app.trim().isEmpty()) {
                 return "Error: Monitor type/application parameter is required";
             }
-            
-            // Get parameter definitions from adapter
-            List<ParamDefine> paramDefines = monitorServiceAdapter.getMonitorParamDefines(app);
+
+            // Get parameter definitions from app service
+            List<ParamDefine> paramDefines = appService.getAppParamDefines(app.toLowerCase().trim());
             
             if (paramDefines == null || paramDefines.isEmpty()) {
                 return String.format("No parameter definitions found for monitor type '%s'. "
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/utils/UtilityClass.java b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/utils/UtilityClass.java
index 64c1a06f87..05e8506a3a 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/utils/UtilityClass.java
+++ b/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/utils/UtilityClass.java
@@ -22,9 +22,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.ai.pojo.dto.Hierarchy;
 
-import java.lang.reflect.Method;
 import java.time.Instant;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
@@ -33,6 +31,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.apache.hertzbeat.manager.pojo.dto.Hierarchy;
 
 /**
  * Utility class providing helper methods for field expression validation, parsing,
@@ -227,51 +226,6 @@ public class UtilityClass {
         return "VALID";
     }
 
-    /**
-     * Helper method to validate operator
-     */
-    public boolean isValidOperator(String operator) {
-        return operator != null && (operator.equals(">") || operator.equals("<")
-                || operator.equals(">=") || operator.equals("<=")
-                || operator.equals("==") || operator.equals("!="));
-    }
-
-    /**
-     * Helper method to validate priority
-     */
-    public boolean isValidPriority(String priority) {
-        return priority != null && (priority.equalsIgnoreCase("critical")
-                || priority.equalsIgnoreCase("warning") || priority.equalsIgnoreCase("info"));
-    }
-
-    /**
-     * Helper method to build expression
-     */
-    public String buildExpression(String metric, String operator, String threshold) {
-        return String.format("%s %s %s", metric, operator, threshold);
-    }
-
-    /**
-     * Helper method to parse existing expression into components
-     */
-    public String[] parseExpression(String expression) {
-        if (expression == null || expression.trim().isEmpty()) {
-            return null;
-        }
-
-        // Simple parsing for basic expressions like "metric > value"
-        String[] operators = {">", "<", ">=", "<=", "==", "!="};
-        for (String op : operators) {
-            if (expression.contains(" " + op + " ")) {
-                String[] parts = expression.split(" " + op + " ");
-                if (parts.length == 2) {
-                    return new String[]{parts[0].trim(), op, parts[1].trim()};
-                }
-            }
-        }
-        return null;
-    }
-
     /**
      * Helper method to parse key-value pairs from a string
      * Format: "key1:value1, key2:value2, ..."
@@ -473,19 +427,6 @@ public class UtilityClass {
         return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
     }
 
-    /**
-     * Parse time range string to milliseconds
-     */
-    public long parseTimeRangeToMillis(String timeRange) {
-        return switch (timeRange.toLowerCase()) {
-            case "1h" -> 60 * 60 * 1000L;
-            case "6h" -> 6 * 60 * 60 * 1000L;
-            case "24h" -> 24 * 60 * 60 * 1000L;
-            case "7d" -> 7 * 24 * 60 * 60 * 1000L;
-            default -> 24 * 60 * 60 * 1000L; // default to 24h
-        };
-    }
-
     /**
      * Helper method to convert monitor status byte to readable text
      * @param status The status byte from monitor
@@ -504,143 +445,6 @@ public class UtilityClass {
         };
     }
 
-    /**
-     * Helper method to get metrics name for a metric type
-     */
-    public String getMetricsNameForType(String metricType) {
-        return switch (metricType.toLowerCase()) {
-            case "cpu" -> "cpu";
-            case "memory" -> "memory";
-            case "disk" -> "disk";
-            case "network" -> "network";
-            default -> "system";
-        };
-    }
-
-    /**
-     * Helper method to check if a field represents usage for a metric type
-     */
-    public boolean isUsageField(String field, String metricType) {
-        if (field == null) return false;
-
-        String fieldLower = field.toLowerCase();
-        String typeLower = metricType.toLowerCase();
-
-        return fieldLower.contains("usage")
-                || fieldLower.contains("percent")
-                || fieldLower.contains("util")
-                || (typeLower.equals("cpu") && (fieldLower.contains("cpu") || fieldLower.contains("idle")))
-                || (typeLower.equals("memory") && fieldLower.contains("memory"))
-                || (typeLower.equals("disk") && fieldLower.contains("disk"));
-    }
-
-    /**
-     * Convert manager module Hierarchy objects to ai-agent module Hierarchy objects
-     * This handles the cross-module DTO conversion to avoid ClassCastException
-     */
-    public List<Hierarchy> convertToAgentHierarchies(List<?> managerHierarchies) {
-        List<Hierarchy> agentHierarchies = new ArrayList<>();
-
-        for (Object managerHierarchy : managerHierarchies) {
-            Hierarchy agentHierarchy = convertToAgentHierarchy(managerHierarchy);
-            agentHierarchies.add(agentHierarchy);
-        }
-
-        return agentHierarchies;
-    }
-
-    /**
-     * Convert a single manager Hierarchy object to ai-agent Hierarchy object using reflection
-     */
-    public Hierarchy convertToAgentHierarchy(Object managerHierarchy) {
-        try {
-            Hierarchy agentHierarchy = new Hierarchy();
-
-            // Use reflection to copy properties from manager DTO to agent DTO
-            Class<?> managerClass = managerHierarchy.getClass();
-
-            // Copy basic properties
-            agentHierarchy.setCategory(getStringField(managerHierarchy, managerClass, "category"));
-            agentHierarchy.setValue(getStringField(managerHierarchy, managerClass, "value"));
-            agentHierarchy.setLabel(getStringField(managerHierarchy, managerClass, "label"));
-            agentHierarchy.setIsLeaf(getBooleanField(managerHierarchy, managerClass, "isLeaf"));
-            agentHierarchy.setHide(getBooleanField(managerHierarchy, managerClass, "hide"));
-            agentHierarchy.setType(getByteField(managerHierarchy, managerClass, "type"));
-            agentHierarchy.setUnit(getStringField(managerHierarchy, managerClass, "unit"));
-
-            // Handle children recursively
-            List<?> managerChildren = getListField(managerHierarchy, managerClass, "children");
-            if (managerChildren != null && !managerChildren.isEmpty()) {
-                List<Hierarchy> agentChildren = convertToAgentHierarchies(managerChildren);
-                agentHierarchy.setChildren(agentChildren);
-            }
-
-            return agentHierarchy;
-
-        } catch (Exception e) {
-            log.error("Failed to convert manager hierarchy to agent hierarchy: {}", e.getMessage(), e);
-            throw new RuntimeException("Failed to convert hierarchy", e);
-        }
-    }
-
-    public String getStringField(Object obj, Class<?> clazz, String fieldName) {
-        try {
-            Method getter = clazz.getMethod("get" + capitalize(fieldName));
-            Object value = getter.invoke(obj);
-            return value != null ? value.toString() : null;
-        } catch (Exception e) {
-            log.debug("Could not get string field '{}': {}", fieldName, e.getMessage());
-            return null;
-        }
-    }
-
-    public Boolean getBooleanField(Object obj, Class<?> clazz, String fieldName) {
-        try {
-            Method getter = clazz.getMethod("get" + capitalize(fieldName));
-            Object value = getter.invoke(obj);
-            return value instanceof Boolean ? (Boolean) value : null;
-        } catch (Exception e) {
-            try {
-                // Try alternative getter pattern for boolean fields
-                Method isGetter = clazz.getMethod("is" + capitalize(fieldName));
-                Object value = isGetter.invoke(obj);
-                return value instanceof Boolean ? (Boolean) value : null;
-            } catch (Exception e2) {
-                log.debug("Could not get boolean field '{}': {}", fieldName, e.getMessage());
-                return null;
-            }
-        }
-    }
-
-    public Byte getByteField(Object obj, Class<?> clazz, String fieldName) {
-        try {
-            Method getter = clazz.getMethod("get" + capitalize(fieldName));
-            Object value = getter.invoke(obj);
-            return value instanceof Byte ? (Byte) value : null;
-        } catch (Exception e) {
-            log.debug("Could not get byte field '{}': {}", fieldName, e.getMessage());
-            return null;
-        }
-    }
-
-    public List<?> getListField(Object obj, Class<?> clazz, String fieldName) {
-        try {
-            Method getter = clazz.getMethod("get" + capitalize(fieldName));
-            Object value = getter.invoke(obj);
-            return value instanceof List ? (List<?>) value : null;
-        } catch (Exception e) {
-            log.debug("Could not get list field '{}': {}", fieldName, e.getMessage());
-            return null;
-        }
-    }
-
-    public String capitalize(String str) {
-        if (str == null || str.isEmpty()) {
-            return str;
-        }
-        return str.substring(0, 1).toUpperCase() + str.substring(1);
-    }
-
 
     /**
      * Extract existing monitor IDs from the alert expression
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java
index b6b066a619..5bb8d6f680 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImpl.java
@@ -24,7 +24,7 @@ import java.util.Properties;
 import java.util.ResourceBundle;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.dto.MailServerConfig;
+import org.apache.hertzbeat.common.entity.dto.MailServerConfig;
 import org.apache.hertzbeat.alert.notice.AlertNoticeException;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/SmsClientFactory.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/SmsClientFactory.java
index 50aebbf9dc..16d5df72ae 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/SmsClientFactory.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/SmsClientFactory.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.alert.service;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.config.SmsConfig;
+import org.apache.hertzbeat.common.entity.dto.sms.SmsConfig;
 import org.apache.hertzbeat.alert.service.impl.SmsLocalSmsClientImpl;
 import org.apache.hertzbeat.alert.service.impl.AwsSmsClientImpl;
 import org.apache.hertzbeat.alert.service.impl.TencentSmsClientImpl;
@@ -151,4 +151,4 @@ public class SmsClientFactory {
                 break;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlibabaSmsClientImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlibabaSmsClientImpl.java
index 93d0f290c2..bf9bdece4b 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlibabaSmsClientImpl.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AlibabaSmsClientImpl.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.alert.service.impl;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.config.AlibabaSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.AlibabaSmsProperties;
 import org.apache.hertzbeat.alert.service.SmsClient;
 import org.apache.hertzbeat.alert.util.CryptoUtils;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
@@ -236,4 +236,4 @@ public class AlibabaSmsClientImpl implements SmsClient {
     public boolean checkConfig() {
         return !(accessKeyId.isBlank() || accessKeySecret.isBlank() || signName.isBlank() || templateCode.isBlank());
     }
-} 
\ No newline at end of file
+} 
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AwsSmsClientImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AwsSmsClientImpl.java
index 34efacbfdd..8fb8c52bbd 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AwsSmsClientImpl.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/AwsSmsClientImpl.java
@@ -20,7 +20,7 @@ package org.apache.hertzbeat.alert.service.impl;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.config.AwsSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.AwsSmsProperties;
 import org.apache.hertzbeat.alert.service.SmsClient;
 import org.apache.hertzbeat.alert.util.CryptoUtils;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImpl.java
index b69ea96cec..47eaafffea 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImpl.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImpl.java
@@ -21,7 +21,7 @@ import com.fasterxml.jackson.databind.JsonNode;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.config.SmslocalSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.SmslocalSmsProperties;
 import org.apache.hertzbeat.alert.service.SmsClient;
 import org.apache.hertzbeat.common.constants.SmsConstants;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentSmsClientImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentSmsClientImpl.java
index e70891f34e..b5cb3e5524 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentSmsClientImpl.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TencentSmsClientImpl.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.alert.service.impl;
 
 import jakarta.xml.bind.DatatypeConverter;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.config.TencentSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.TencentSmsProperties;
 import org.apache.hertzbeat.alert.service.SmsClient;
 import org.apache.hertzbeat.alert.util.CryptoUtils;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TwilioSmsClientImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TwilioSmsClientImpl.java
index 5a6ba033f6..67059d776d 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TwilioSmsClientImpl.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/TwilioSmsClientImpl.java
@@ -19,7 +19,7 @@ package org.apache.hertzbeat.alert.service.impl;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.config.TwilioSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.TwilioSmsProperties;
 import org.apache.hertzbeat.alert.service.SmsClient;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
@@ -168,4 +168,4 @@ public class TwilioSmsClientImpl implements SmsClient {
     public boolean checkConfig() {
         return !(accountSid.isBlank() || authToken.isBlank() || twilioPhoneNumber.isBlank());
     }
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImpl.java b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImpl.java
index bf8798cc2b..54f43781d2 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImpl.java
+++ b/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImpl.java
@@ -18,7 +18,7 @@
 package org.apache.hertzbeat.alert.service.impl;
 
 import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.alert.config.UniSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.UniSmsProperties;
 import org.apache.hertzbeat.alert.service.SmsClient;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
@@ -190,4 +190,4 @@ public class UniSmsClientImpl implements SmsClient {
 
         return true;
     }
-} 
\ No newline at end of file
+} 
diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java
index f9794fd1af..237e5a2ced 100644
--- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java
+++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/notice/impl/EmailAlertNotifyHandlerImplTest.java
@@ -27,7 +27,7 @@ import static org.mockito.Mockito.when;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.Properties;
-import org.apache.hertzbeat.alert.dto.MailServerConfig;
+import org.apache.hertzbeat.common.entity.dto.MailServerConfig;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AwsSmsClientImplTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AwsSmsClientImplTest.java
index 30705751e3..d8e9573267 100644
--- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AwsSmsClientImplTest.java
+++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/AwsSmsClientImplTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.hertzbeat.alert.service;
 
-import org.apache.hertzbeat.alert.config.AwsSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.AwsSmsProperties;
 import org.apache.hertzbeat.alert.service.impl.AwsSmsClientImpl;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/SmsClientFactoryTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/SmsClientFactoryTest.java
index d40e112812..a95402129f 100644
--- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/SmsClientFactoryTest.java
+++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/SmsClientFactoryTest.java
@@ -19,8 +19,8 @@ package org.apache.hertzbeat.alert.service;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.hertzbeat.alert.config.SmsConfig;
-import org.apache.hertzbeat.alert.config.SmslocalSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.SmsConfig;
+import org.apache.hertzbeat.common.entity.dto.sms.SmslocalSmsProperties;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
 import org.apache.hertzbeat.common.entity.manager.GeneralConfig;
@@ -89,4 +89,4 @@ public class SmsClientFactoryTest {
         assertNull(smsClientFactory.getSmsClient());
     }
 
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/TwilioSmsClientImplTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/TwilioSmsClientImplTest.java
index 2c32417ea8..ef4f47c553 100644
--- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/TwilioSmsClientImplTest.java
+++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/TwilioSmsClientImplTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.hertzbeat.alert.service;
 
-import org.apache.hertzbeat.alert.config.TwilioSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.TwilioSmsProperties;
 import org.apache.hertzbeat.alert.service.impl.TwilioSmsClientImpl;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -61,4 +61,4 @@ class TwilioSmsClientImplTest {
 
         assertEquals(expected, twilioSmsClient.checkConfig());
     }
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImplTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImplTest.java
index 1cbc8b017d..098560ef24 100644
--- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImplTest.java
+++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/SmsLocalSmsClientImplTest.java
@@ -18,7 +18,7 @@
 package org.apache.hertzbeat.alert.service.impl;
 
 import com.google.common.collect.Lists;
-import org.apache.hertzbeat.alert.config.SmslocalSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.SmslocalSmsProperties;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
 import org.apache.hertzbeat.common.entity.alerter.SingleAlert;
@@ -70,4 +70,4 @@ public class SmsLocalSmsClientImplTest {
                 () -> smsLocalSmsClient.sendMessage(noticeReceiver, null, groupAlert));
     }
 
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImplTest.java b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImplTest.java
index 95ca6cda44..86aff19e32 100644
--- a/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImplTest.java
+++ b/hertzbeat-alerter/src/test/java/org/apache/hertzbeat/alert/service/impl/UniSmsClientImplTest.java
@@ -17,7 +17,7 @@
 
 package org.apache.hertzbeat.alert.service.impl;
 
-import org.apache.hertzbeat.alert.config.UniSmsProperties;
+import org.apache.hertzbeat.common.entity.dto.sms.UniSmsProperties;
 import org.apache.hertzbeat.common.entity.alerter.GroupAlert;
 import org.apache.hertzbeat.common.entity.alerter.NoticeReceiver;
 import org.apache.hertzbeat.common.support.exception.SendMessageException;
@@ -82,4 +82,4 @@ public class UniSmsClientImplTest {
     }
 
 
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/entity/OpenAiConfig.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/ai/ChatConversation.java
similarity index 65%
copy from hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/entity/OpenAiConfig.java
copy to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/ai/ChatConversation.java
index 7795acea78..ce6129c756 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/entity/OpenAiConfig.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/ai/ChatConversation.java
@@ -15,66 +15,70 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.ai.entity;
+package org.apache.hertzbeat.common.entity.ai;
 
 import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
-import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
-
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
 import jakarta.persistence.EntityListeners;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.OneToMany;
 import jakarta.persistence.Table;
-import jakarta.validation.constraints.NotBlank;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
 import org.springframework.data.annotation.CreatedBy;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.annotation.LastModifiedBy;
 import org.springframework.data.annotation.LastModifiedDate;
 import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
- * OpenAI Agent Config Entity
+ * Entity for storing AI chat conversation metadata
  */
-@Entity
-@Table(name = "hzb_ai_agent_config")
 @Data
 @Builder
+@Entity
+@EntityListeners(AuditingEntityListener.class)
+@Table(name = "hzb_ai_conversation")
 @AllArgsConstructor
 @NoArgsConstructor
-@Schema(description = "OpenAI Agent config entity")
-@EntityListeners(AuditingEntityListener.class)
-public class OpenAiConfig {
+public class ChatConversation {
 
     @Id
-    @Schema(title = "Config type: openai, primary key", description = "Config type: openai, primary key",
-            accessMode = READ_WRITE)
-    @NotBlank(message = "type can not null")
-    private String type;
-
-    @Schema(title = "Config content", description = "Config content,format json", accessMode = READ_WRITE)
-    @Column(length = 8192)
-    private String content;
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    
+    @Schema(title = "conversation title")
+    private String title;
 
     @Schema(title = "The creator of this record", example = "tom", accessMode = READ_ONLY)
     @CreatedBy
     private String creator;
 
-    @Schema(title = "This record was last modified by", example = "tom", accessMode = READ_ONLY)
+    @Schema(title = "The modifier of this record", example = "tom", accessMode = READ_ONLY)
     @LastModifiedBy
     private String modifier;
 
-    @Schema(title = "This record creation time (millisecond timestamp)", accessMode = READ_ONLY)
+    @Schema(title = "Record create time", example = "1612198922000", accessMode = READ_ONLY)
     @CreatedDate
     private LocalDateTime gmtCreate;
 
-    @Schema(title = "Record the latest modification time (timestamp in milliseconds)", accessMode = READ_ONLY)
+    @Schema(title = "Record modify time", example = "1612198444000", accessMode = READ_ONLY)
     @LastModifiedDate
     private LocalDateTime gmtUpdate;
+
+    /**
+     * List of messages in this conversation (one-to-many relationship)
+     */
+    @OneToMany
+    @JoinColumn(name = "conversation_id")
+    private List<ChatMessage> messages;
 }
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/entity/OpenAiConfig.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/ai/ChatMessage.java
similarity index 67%
rename from hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/entity/OpenAiConfig.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/ai/ChatMessage.java
index 7795acea78..fc8e14d1fe 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/entity/OpenAiConfig.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/ai/ChatMessage.java
@@ -15,66 +15,74 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.ai.entity;
+package org.apache.hertzbeat.common.entity.ai;
 
 import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_ONLY;
-import static io.swagger.v3.oas.annotations.media.Schema.AccessMode.READ_WRITE;
-
 import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
 import jakarta.persistence.EntityListeners;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.Lob;
+
 import jakarta.persistence.Table;
 import jakarta.validation.constraints.NotBlank;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
+import java.time.LocalDateTime;
 import org.springframework.data.annotation.CreatedBy;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.annotation.LastModifiedBy;
 import org.springframework.data.annotation.LastModifiedDate;
 import org.springframework.data.jpa.domain.support.AuditingEntityListener;
-
-import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
 /**
- * OpenAI Agent Config Entity
+ * Entity for storing individual chat messages in conversations
  */
-@Entity
-@Table(name = "hzb_ai_agent_config")
 @Data
 @Builder
+@Entity
+@EntityListeners(AuditingEntityListener.class)
+@Table(name = "hzb_ai_message", indexes = {
+    @Index(name = "idx_message_conversation_id", columnList = "conversation_id")
+})
 @AllArgsConstructor
 @NoArgsConstructor
-@Schema(description = "OpenAI Agent config entity")
-@EntityListeners(AuditingEntityListener.class)
-public class OpenAiConfig {
+public class ChatMessage {
 
     @Id
-    @Schema(title = "Config type: openai, primary key", description = "Config type: openai, primary key",
-            accessMode = READ_WRITE)
-    @NotBlank(message = "type can not null")
-    private String type;
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    
+    @Schema(title = "conversation id")
+    private Long conversationId;
 
-    @Schema(title = "Config content", description = "Config content,format json", accessMode = READ_WRITE)
-    @Column(length = 8192)
+    @Schema(title = "message content")
+    @Lob
+    @NotBlank
     private String content;
 
+    @Schema(title = "message role: user, system")
+    private String role;
+
     @Schema(title = "The creator of this record", example = "tom", accessMode = READ_ONLY)
     @CreatedBy
     private String creator;
 
-    @Schema(title = "This record was last modified by", example = "tom", accessMode = READ_ONLY)
+    @Schema(title = "The modifier of this record", example = "tom", accessMode = READ_ONLY)
     @LastModifiedBy
     private String modifier;
 
-    @Schema(title = "This record creation time (millisecond timestamp)", accessMode = READ_ONLY)
+    @Schema(title = "Record create time", example = "1612198922000", accessMode = READ_ONLY)
     @CreatedDate
     private LocalDateTime gmtCreate;
 
-    @Schema(title = "Record the latest modification time (timestamp in milliseconds)", accessMode = READ_ONLY)
+    @Schema(title = "Record modify time", example = "1612198444000", accessMode = READ_ONLY)
     @LastModifiedDate
     private LocalDateTime gmtUpdate;
+    
 }
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/MailServerConfig.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/MailServerConfig.java
similarity index 97%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/MailServerConfig.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/MailServerConfig.java
index 343884b167..3c99b34ab6 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/dto/MailServerConfig.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/MailServerConfig.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.dto;
+package org.apache.hertzbeat.common.entity.dto;
 
 import jakarta.validation.constraints.Email;
 import jakarta.validation.constraints.Max;
diff --git a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ModelProviderConfig.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/ModelProviderConfig.java
similarity index 81%
rename from hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ModelProviderConfig.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/ModelProviderConfig.java
index e463dfda26..527f65da72 100644
--- a/hertzbeat-ai/src/main/java/org/apache/hertzbeat/ai/pojo/dto/ModelProviderConfig.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/ModelProviderConfig.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.ai.pojo.dto;
+package org.apache.hertzbeat.common.entity.dto;
 
 import io.swagger.v3.oas.annotations.media.Schema;
 import jakarta.validation.constraints.NotBlank;
@@ -32,15 +32,6 @@ import lombok.NoArgsConstructor;
 @Schema(description = "LLM Model Provider configuration")
 public class ModelProviderConfig {
     
-    @Schema(title = "Enable Provider", description = "Whether Provider is enabled", example = "true")
-    private boolean enable = false;
-    
-    @Schema(title = "Check the provider available status")
-    private boolean status = false;
-    
-    @Schema(title = "The error message when provider status check failed")
-    private String error;
-    
     @Schema(title = "Model type, text-generate, vision")
     private String type;
     
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/AlibabaSmsProperties.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/AlibabaSmsProperties.java
similarity index 96%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/AlibabaSmsProperties.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/AlibabaSmsProperties.java
index 081e2c687b..4de833f382 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/AlibabaSmsProperties.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/AlibabaSmsProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.config;
+package org.apache.hertzbeat.common.entity.dto.sms;
 
 import jakarta.validation.constraints.NotBlank;
 import lombok.AllArgsConstructor;
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/AwsSmsProperties.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/AwsSmsProperties.java
similarity index 96%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/AwsSmsProperties.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/AwsSmsProperties.java
index 15c7d4be40..6e0408764a 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/AwsSmsProperties.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/AwsSmsProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.config;
+package org.apache.hertzbeat.common.entity.dto.sms;
 
 import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/SmsConfig.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/SmsConfig.java
similarity index 97%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/SmsConfig.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/SmsConfig.java
index 3ceb6deb78..2b2c3a5f6a 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/SmsConfig.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/SmsConfig.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.config;
+package org.apache.hertzbeat.common.entity.dto.sms;
 
 import jakarta.validation.constraints.NotBlank;
 import lombok.AllArgsConstructor;
@@ -74,4 +74,4 @@ public class SmsConfig {
      * Smslocal SMS configuration
      */
     private SmslocalSmsProperties smslocal;
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/SmslocalSmsProperties.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/SmslocalSmsProperties.java
similarity index 95%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/SmslocalSmsProperties.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/SmslocalSmsProperties.java
index 85dbb5aa40..3d39d5f6a1 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/SmslocalSmsProperties.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/SmslocalSmsProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.config;
+package org.apache.hertzbeat.common.entity.dto.sms;
 
 
 import lombok.AllArgsConstructor;
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/TencentSmsProperties.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/TencentSmsProperties.java
similarity index 96%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/TencentSmsProperties.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/TencentSmsProperties.java
index 9ab93a13fd..7394dc09ad 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/TencentSmsProperties.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/TencentSmsProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.config;
+package org.apache.hertzbeat.common.entity.dto.sms;
 
 import jakarta.validation.constraints.NotBlank;
 import lombok.AllArgsConstructor;
@@ -58,4 +58,4 @@ public class TencentSmsProperties {
      */
     @NotBlank(message = "templateId cannot be null")
     private String templateId;
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/TwilioSmsProperties.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/TwilioSmsProperties.java
similarity index 96%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/TwilioSmsProperties.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/TwilioSmsProperties.java
index 26c74bfd9b..57013ad8d8 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/TwilioSmsProperties.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/TwilioSmsProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.config;
+package org.apache.hertzbeat.common.entity.dto.sms;
 
 import jakarta.validation.constraints.NotBlank;
 import lombok.AllArgsConstructor;
@@ -46,4 +46,4 @@ public class TwilioSmsProperties {
      */
     @NotBlank(message = "Twilio Phone Number cannot be empty")
     private String twilioPhoneNumber;
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/UniSmsProperties.java b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/UniSmsProperties.java
similarity index 96%
rename from hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/UniSmsProperties.java
rename to hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/UniSmsProperties.java
index f7c18ac043..ea32e4b4de 100644
--- a/hertzbeat-alerter/src/main/java/org/apache/hertzbeat/alert/config/UniSmsProperties.java
+++ b/hertzbeat-common/src/main/java/org/apache/hertzbeat/common/entity/dto/sms/UniSmsProperties.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.hertzbeat.alert.config;
+package org.apache.hertzbeat.common.entity.dto.sms;
 
 import jakarta.validation.constraints.NotBlank;
 import lombok.AllArgsConstructor;
@@ -57,4 +57,4 @@ public class UniSmsProperties {
      */
     @NotBlank(message = "authMode cannot be null")
     private String authMode = "simple";
-} 
\ No newline at end of file
+} 
diff --git a/hertzbeat-manager/pom.xml b/hertzbeat-manager/pom.xml
index 31650f8a2a..5f3671242c 100644
--- a/hertzbeat-manager/pom.xml
+++ b/hertzbeat-manager/pom.xml
@@ -212,11 +212,6 @@
             <groupId>org.apache.arrow</groupId>
             <artifactId>arrow-memory-netty</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.apache.hertzbeat</groupId>
-            <artifactId>hertzbeat-ai</artifactId>
-            <version>${project.version}</version>
-        </dependency>
         <dependency>
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-registry-prometheus</artifactId>
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/AiProperties.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/AiProperties.java
deleted file mode 100644
index f2528769d4..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/config/AiProperties.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.hertzbeat.manager.config;
-
-import lombok.Data;
-import org.apache.hertzbeat.common.constants.ConfigConstants;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * AiProperties
- */
-
-@Data
-@Configuration
-@ConfigurationProperties(prefix =
-        ConfigConstants.FunctionModuleConstants.AI)
-public class AiProperties {
-
-    /**
-     * AI Type: zhiPu, alibabaAi, kimiAi, sparkDesk
-     */
-    private String type;
-
-    /**
-     * Model name: glm-4, qwen-turboo, moonshot-v1-8k, generalv3.5
-     */
-    private String model;
-
-    /**
-     * API key
-     */
-    private String apiKey;
-
-    /**
-     * At present, only IFLYTEK large model needs to be filled in
-     */
-    private String apiSecret;
-
-    /**
-     * API URL for the Ollama AI service.
-     */
-    private String apiUrl;
-
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/AiController.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/AiController.java
deleted file mode 100644
index fb1a192b05..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/controller/AiController.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.hertzbeat.manager.controller;
-
-import static org.springframework.http.MediaType.TEXT_EVENT_STREAM_VALUE;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.pojo.dto.AiControllerRequestParam;
-import org.apache.hertzbeat.manager.service.ai.AiService;
-import org.apache.hertzbeat.manager.service.ai.factory.AiServiceFactoryImpl;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.util.Assert;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import reactor.core.publisher.Flux;
-
-/**
- * AI Management API
- */
-@Tag(name = "AI Manage API")
-@RestController
-@RequestMapping(value = "/api/ai")
-public class AiController {
-
-    /**
-     * AI beanFactory
-     */
-    @Autowired(required = false)
-    private AiServiceFactoryImpl aiServiceFactory;
-
-    @Autowired
-    private AiProperties aiProperties;
-
-    /**
-     * request AI
-     * @param requestParam          request text
-     * @return                      AI response
-     */
-    @PostMapping(path = "/get", produces = {TEXT_EVENT_STREAM_VALUE})
-    @Operation(summary = "Artificial intelligence questions and Answers",
-            description = "Artificial intelligence questions and Answers")
-    public Flux<ServerSentEvent<String>> requestAi(@Parameter(description = "Request text", example = "Who are you")
-                                                       @RequestBody AiControllerRequestParam requestParam)  {
-        Assert.notNull(aiServiceFactory, "please check that your type value is consistent with the documentation on the website");
-        AiService aiServiceImplBean = aiServiceFactory.getAiServiceImplBean(aiProperties.getType());
-        return aiServiceImplBean.requestAi(requestParam.getText());
-    }
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/OpenAiRequestParamDTO.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/OpenAiRequestParamDTO.java
deleted file mode 100644
index 7c51e1abec..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/OpenAiRequestParamDTO.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.hertzbeat.manager.pojo.dto;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.List;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * openAi Request param
- */
-
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@Builder
-public class OpenAiRequestParamDTO {
-
-    /**
-     * ai version
-     */
-    private String model;
-
-    /**
-     * request message
-     */
-    private List<AiMessage> messages;
-
-    /**
-     * The sampling temperature, which controls the randomness of the output, must be positive
-     * The value ranges from 0.0 to 1.0, and cannot be equal to 0. The default value is 0.95.
-     * The larger the value, the more random and creative the output will be. The smaller the value, the more stable or certain the output will be
-     * You are advised to adjust top_p or temperature parameters based on application scenarios, but do not adjust the two parameters at the same time
-     */
-    private float temperature;
-
-    /**
-     * The model outputs the maximum tokens, with a maximum output of 8192 and a default value of 1024
-     */
-    @JsonProperty("max_tokens")
-    private Integer maxTokens;
-
-    /**
-     * stream response
-     */
-    private Boolean stream = Boolean.FALSE;
-
-
-}
-
-
-
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/OpenAiResponse.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/OpenAiResponse.java
deleted file mode 100644
index 3c97739f25..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/OpenAiResponse.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.hertzbeat.manager.pojo.dto;
-
-import com.alibaba.fastjson.JSON;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.List;
-import java.util.Objects;
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.codec.ServerSentEvent;
-
-/**
- * openAi Response
- */
-@Data
-@AllArgsConstructor
-@NoArgsConstructor
-@Slf4j
-public class OpenAiResponse {
-
-    /**
-     * Task order number generated by the AI open platform. Use this order number when invoking the request result interface
-     */
-    private String id;
-
-    /**
-     * The request creation time is a Unix timestamp in seconds
-     */
-    private Long created;
-
-    /**
-     * response message
-     */
-    private List<Choice> choices;
-
-    /**
-     * Returns the number of tokens invoked by the model at the end.
-     */
-    private Tokens usage;
-
-    /**
-     * Choice
-     */
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public class Choice {
-        private int index;
-        private AiMessage delta;
-    }
-
-    /**
-     * Tokens
-     */
-    @Data
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public class Tokens {
-
-        /**
-         * The number of tokens entered by users
-         */
-        @JsonProperty("prompt_tokens")
-        private Integer promptTokens;
-
-        /**
-         * The number of tokens that the model outputs
-         */
-        @JsonProperty("completion_tokens")
-        private Integer completionTokens;
-
-        /**
-         * Total number of tokens
-         */
-        @JsonProperty("total_tokens")
-        private Integer totalTokens;
-    }
-
-    public static ServerSentEvent<String> convertToResponse(String aiRes) {
-        try {
-            OpenAiResponse openAiResponse = JSON.parseObject(aiRes, OpenAiResponse.class);
-            if (Objects.nonNull(openAiResponse)) {
-                OpenAiResponse.Choice choice = openAiResponse.getChoices().get(0);
-                String content = choice.getDelta().getContent();
-                return ServerSentEvent.<String>builder()
-                        .data(content)
-                        .build();
-            }
-        } catch (Exception e) {
-            log.info("convertToResponse Exception:{}", e.toString());
-            throw e;
-        }
-
-        return ServerSentEvent.<String>builder().build();
-    }
-}
-
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/TemplateConfig.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/TemplateConfig.java
index 29b5b85382..f932ccf4f7 100644
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/TemplateConfig.java
+++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/TemplateConfig.java
@@ -51,6 +51,7 @@ public class TemplateConfig {
         /**
          * Is hide this app in main menus layout, only for app type, default true
          */
+        @Builder.Default
         private boolean hide = true;
     }
 }
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/AiService.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/AiService.java
deleted file mode 100644
index de8e683ed9..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/AiService.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai;
-
-
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.springframework.http.codec.ServerSentEvent;
-import reactor.core.publisher.Flux;
-
-
-/**
- * AI Service
- */
-public interface AiService {
-
-    /**
-     * get AI type
-     * @return     type
-     */
-    AiTypeEnum getType();
-
-    /**
-     * AI response
-     * @param text  text
-     * @return      AI response
-     */
-    Flux<ServerSentEvent<String>> requestAi(String text);
-
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/AlibabaAiServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/AlibabaAiServiceImpl.java
deleted file mode 100644
index f9c1236ab7..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/AlibabaAiServiceImpl.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai;
-
-import java.util.List;
-import java.util.Objects;
-import javax.annotation.PostConstruct;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.common.constants.AiConstants;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.pojo.dto.AiMessage;
-import org.apache.hertzbeat.manager.pojo.dto.AliAiRequestParamDTO;
-import org.apache.hertzbeat.manager.pojo.dto.AliAiResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Flux;
-
-
-/**
- * alibaba Ai
- */
-@Service("AlibabaAiServiceImpl")
-@ConditionalOnProperty(prefix = "ai", name = "type", havingValue = "alibabaAi")
-@Slf4j
-public class AlibabaAiServiceImpl implements AiService {
-
-    @Autowired
-    private AiProperties aiProperties;
-
-    private WebClient webClient;
-
-    @PostConstruct
-    private void init() {
-        this.webClient = WebClient.builder()
-                .baseUrl(AiConstants.AliAiConstants.URL)
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + aiProperties.getApiKey())
-                //sse
-                .defaultHeader(HttpHeaders.ACCEPT, MediaType.TEXT_EVENT_STREAM_VALUE)
-                .exchangeStrategies(ExchangeStrategies.builder()
-                        .codecs(item -> item.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
-                        .build())
-                .build();
-    }
-
-    @Override
-    public AiTypeEnum getType() {
-        return AiTypeEnum.alibabaAi;
-    }
-
-    @Override
-    public Flux<ServerSentEvent<String>> requestAi(String text) {
-        checkParam(text, aiProperties.getModel(), aiProperties.getApiKey());
-        AliAiRequestParamDTO aliAiRequestParamDTO = AliAiRequestParamDTO.builder()
-                .model(aiProperties.getModel())
-                .input(AliAiRequestParamDTO.Input.builder()
-                        .messages(List.of(new AiMessage(AiConstants.AliAiConstants.REQUEST_ROLE, text)))
-                        .build())
-                .parameters(AliAiRequestParamDTO.Parameters.builder()
-                        .maxTokens(AiConstants.AliAiConstants.MAX_TOKENS)
-                        .temperature(AiConstants.AliAiConstants.TEMPERATURE)
-                        .enableSearch(true)
-                        .resultFormat("message")
-                        .incrementalOutput(true)
-                        .build())
-                .build();
-
-        return webClient.post()
-                .body(BodyInserters.fromValue(aliAiRequestParamDTO))
-                .retrieve()
-                .bodyToFlux(AliAiResponse.class)
-                .map(aliAiResponse -> {
-                    if (Objects.nonNull(aliAiResponse)) {
-                        List<AliAiResponse.Choice> choices = aliAiResponse.getOutput().getChoices();
-                        if (CollectionUtils.isEmpty(choices)) {
-                            return ServerSentEvent.<String>builder().build();
-                        }
-                        String content = choices.get(0).getMessage().getContent();
-                        return ServerSentEvent.<String>builder()
-                                .data(content)
-                                .build();
-                    }
-                    return ServerSentEvent.<String>builder().build();
-                })
-                .doOnError(error -> log.info("AlibabaAiServiceImpl.requestAi exception:{}", error.getMessage()));
-    }
-
-    private void checkParam(String param, String apiKey, String model) {
-        Assert.notNull(param, "text is null");
-        Assert.notNull(model, "model is null");
-        Assert.notNull(apiKey, "ai.api-key is null");
-    }
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/KimiAiServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/KimiAiServiceImpl.java
deleted file mode 100644
index 5063949150..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/KimiAiServiceImpl.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai;
-
-import java.util.List;
-import javax.annotation.PostConstruct;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.common.constants.AiConstants;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.pojo.dto.AiMessage;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiRequestParamDTO;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Flux;
-
-/**
- * Kimi Ai
- */
-@Service("KimiAiServiceImpl")
-@ConditionalOnProperty(prefix = "ai", name = "type", havingValue = "kimiAi")
-@Slf4j
-public class KimiAiServiceImpl implements AiService {
-
-    @Autowired
-    private AiProperties aiProperties;
-
-    private WebClient webClient;
-
-    @PostConstruct
-    private void init() {
-        this.webClient = WebClient.builder()
-                .baseUrl(AiConstants.KimiAiConstants.URL)
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + aiProperties.getApiKey())
-                .exchangeStrategies(ExchangeStrategies.builder()
-                        .codecs(item -> item.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
-                        .build())
-                .build();
-    }
-
-    @Override
-    public AiTypeEnum getType() {
-        return AiTypeEnum.kimiAi;
-    }
-
-    @Override
-    public Flux<ServerSentEvent<String>> requestAi(String text) {
-        checkParam(text, aiProperties.getModel(), aiProperties.getApiKey());
-        OpenAiRequestParamDTO zhiPuRequestParamDTO = OpenAiRequestParamDTO.builder()
-                .model(aiProperties.getModel())
-                .stream(Boolean.TRUE)
-                .maxTokens(AiConstants.KimiAiConstants.MAX_TOKENS)
-                .temperature(AiConstants.KimiAiConstants.TEMPERATURE)
-                .messages(List.of(new AiMessage(AiConstants.KimiAiConstants.REQUEST_ROLE, text)))
-                .build();
-
-        return webClient.post()
-                .body(BodyInserters.fromValue(zhiPuRequestParamDTO))
-                .retrieve()
-                .bodyToFlux(String.class)
-                .filter(aiResponse -> !"[DONE]".equals(aiResponse))
-                .map(OpenAiResponse::convertToResponse)
-                .doOnError(error -> log.info("KimiAiServiceImpl.requestAi exception:{}", error.getMessage()));
-    }
-
-    private void checkParam(String param, String model, String apiKey) {
-        Assert.notNull(param, "text is null");
-        Assert.notNull(model, "model is null");
-        Assert.notNull(apiKey, "ai.api-key is null");
-    }
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/OllamaAiService.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/OllamaAiService.java
deleted file mode 100644
index 8d3a7b3130..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/OllamaAiService.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai;
-
-import io.jsonwebtoken.lang.Assert;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.common.constants.AiConstants;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.pojo.dto.AiMessage;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiRequestParamDTO;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.stereotype.Service;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Flux;
-
-import javax.annotation.PostConstruct;
-import java.util.List;
-
-/**
- * Ollama service
- */
-@Service("OllamaServiceImpl")
-@ConditionalOnProperty(prefix = "ai", name = "type", havingValue = "ollama")
-@Slf4j
-public class OllamaAiService implements AiService{
-    @Autowired
-    private AiProperties aiProperties;
-
-    private WebClient webClient;
-
-    @PostConstruct
-    private void init() {
-        Assert.notNull(aiProperties.getApiUrl(), "Ollama API URL is null");
-        this.webClient = WebClient.builder()
-                .baseUrl(aiProperties.getApiUrl())
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .exchangeStrategies(ExchangeStrategies.builder()
-                        .codecs(item -> item.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
-                        .build())
-                .build();
-    }
-
-    @Override
-    public AiTypeEnum getType() {
-        return AiTypeEnum.ollama;
-    }
-
-    @Override
-    public Flux<ServerSentEvent<String>> requestAi(String text) {
-        checkParam(text, aiProperties.getModel());
-        OpenAiRequestParamDTO ollamaParam = OpenAiRequestParamDTO.builder()
-                .model(aiProperties.getModel())
-                .stream(Boolean.TRUE)
-                .maxTokens(AiConstants.OllamaConstants.MAX_TOKENS)
-                .temperature(AiConstants.OllamaConstants.TEMPERATURE)
-                .messages(List.of(new AiMessage(AiConstants.OllamaConstants.REQUEST_ROLE, text)))
-                .build();
-
-        return webClient.post()
-                .body(BodyInserters.fromValue(ollamaParam))
-                .retrieve()
-                .bodyToFlux(String.class)
-                .filter(aiResponse -> !"[DONE]".equals(aiResponse))
-                .map(OpenAiResponse::convertToResponse)
-                .doOnError(error -> log.info("OllamaAiService.requestAi exception:{}", error.getMessage()));
-    }
-
-    private void checkParam(String param, String model) {
-        Assert.notNull(param, "text is null");
-        Assert.notNull(model, "model is null");
-    }
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/OpenRouterServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/OpenRouterServiceImpl.java
deleted file mode 100644
index 417c92d25c..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/OpenRouterServiceImpl.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai;
-
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.common.constants.AiConstants;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.pojo.dto.AiMessage;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiRequestParamDTO;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Flux;
-
-import javax.annotation.PostConstruct;
-import java.util.List;
-
-/**
- * OpenRouter service
- */
-@Service("OpenRouterServiceImpl")
-@ConditionalOnProperty(prefix = "ai", name = "type", havingValue = "openRouter")
-@Slf4j
-public class OpenRouterServiceImpl implements AiService {
-
-    @Autowired
-    private AiProperties aiProperties;
-
-    private WebClient webClient;
-
-    @PostConstruct
-    private void init() {
-        this.webClient = WebClient.builder()
-                .baseUrl(AiConstants.OpenRouterConstants.URL)
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + aiProperties.getApiKey())
-                .exchangeStrategies(ExchangeStrategies.builder()
-                        .codecs(item -> item.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
-                        .build())
-                .build();
-    }
-
-    @Override
-    public AiTypeEnum getType() {
-        return AiTypeEnum.openRouter;
-    }
-
-    @Override
-    public Flux<ServerSentEvent<String>> requestAi(String text) {
-        checkParam(text, aiProperties.getModel(), aiProperties.getApiKey());
-        OpenAiRequestParamDTO openRouterParam = OpenAiRequestParamDTO.builder()
-                .model(aiProperties.getModel())
-                .stream(Boolean.TRUE)
-                .maxTokens(AiConstants.OpenRouterConstants.MAX_TOKENS)
-                .temperature(AiConstants.OpenRouterConstants.TEMPERATURE)
-                .messages(List.of(new AiMessage(AiConstants.OpenRouterConstants.REQUEST_ROLE, text)))
-                .build();
-
-        return webClient.post()
-                .body(BodyInserters.fromValue(openRouterParam))
-                .retrieve()
-                .bodyToFlux(String.class)
-                .filter(aiResponse -> !"[DONE]".equals(aiResponse))
-                .map(OpenAiResponse::convertToResponse)
-                .doOnError(error -> log.info("OpenRouterAiServiceImpl.requestAi exception:{}", error.getMessage()));
-    }
-
-    private void checkParam(String param, String model, String apiKey) {
-        Assert.notNull(param, "text is null");
-        Assert.notNull(model, "model is null");
-        Assert.notNull(apiKey, "ai.api-key is null");
-    }
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/SparkDeskAiServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/SparkDeskAiServiceImpl.java
deleted file mode 100644
index c35b1f664e..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/SparkDeskAiServiceImpl.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai;
-
-import java.util.List;
-import javax.annotation.PostConstruct;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.common.constants.AiConstants;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.pojo.dto.AiMessage;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiRequestParamDTO;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Flux;
-
-
-/**
- * sparkDesk AI
- */
-@Service("SparkDeskAiServiceImpl")
-@ConditionalOnProperty(prefix = "ai", name = "type", havingValue = "sparkDesk")
-@Slf4j
-public class SparkDeskAiServiceImpl implements AiService {
-
-    @Autowired
-    private AiProperties aiProperties;
-
-    private WebClient webClient;
-
-    @PostConstruct
-    private void init() {
-        StringBuilder sb = new StringBuilder();
-        String bearer = sb.append("Bearer ")
-                          .append(aiProperties.getApiKey())
-                          .append(":").append(aiProperties.getApiSecret()).toString();
-
-        this.webClient = WebClient.builder()
-                .baseUrl(AiConstants.SparkDeskConstants.SPARK_ULTRA_URL)
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .defaultHeader(HttpHeaders.AUTHORIZATION, bearer)
-                .exchangeStrategies(ExchangeStrategies.builder()
-                        .codecs(item -> item.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
-                        .build())
-                .build();
-    }
-
-    @Override
-    public AiTypeEnum getType() {
-        return AiTypeEnum.sparkDesk;
-    }
-
-    @Override
-    public Flux<ServerSentEvent<String>> requestAi(String text) {
-        checkParam(text, aiProperties.getApiKey(), aiProperties.getModel());
-        OpenAiRequestParamDTO zhiPuRequestParamDTO = OpenAiRequestParamDTO.builder()
-                .model(aiProperties.getModel())
-                //sse
-                .stream(Boolean.TRUE)
-                .maxTokens(AiConstants.SparkDeskConstants.MAX_TOKENS)
-                .temperature(AiConstants.SparkDeskConstants.TEMPERATURE)
-                .messages(List.of(new AiMessage(AiConstants.SparkDeskConstants.REQUEST_ROLE, text)))
-                .build();
-
-        return webClient.post()
-                .body(BodyInserters.fromValue(zhiPuRequestParamDTO))
-                .retrieve()
-                .bodyToFlux(String.class)
-                .filter(aiResponse -> !"[DONE]".equals(aiResponse))
-                .map(OpenAiResponse::convertToResponse)
-                .doOnError(error -> log.info("SparkDeskAiServiceImpl.requestAi exception:{}", error.getMessage()));
-
-    }
-
-    private void checkParam(String param, String apiKey, String model) {
-        Assert.notNull(param, "text is null");
-        Assert.notNull(model, "model is null");
-        Assert.notNull(apiKey, "ai.api-key is null");
-    }
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/ZhiPuServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/ZhiPuServiceImpl.java
deleted file mode 100644
index 1a8ef2d934..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/ZhiPuServiceImpl.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai;
-
-
-import java.util.List;
-import javax.annotation.PostConstruct;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.hertzbeat.common.constants.AiConstants;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.pojo.dto.AiMessage;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiRequestParamDTO;
-import org.apache.hertzbeat.manager.pojo.dto.OpenAiResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-import org.springframework.web.reactive.function.BodyInserters;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Flux;
-
-
-/**
- * ZhiPu AI
- */
-@Service("ZhiPuServiceImpl")
-@ConditionalOnProperty(prefix = "ai", name = "type", havingValue = "zhiPu")
-@Slf4j
-public class ZhiPuServiceImpl implements AiService {
-
-    @Autowired
-    private AiProperties aiProperties;
-
-    private WebClient webClient;
-
-    @PostConstruct
-    private void init() {
-        this.webClient = WebClient.builder()
-                .baseUrl(AiConstants.ZhiPuConstants.URL)
-                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
-                .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + aiProperties.getApiKey())
-                .exchangeStrategies(ExchangeStrategies.builder()
-                        .codecs(item -> item.defaultCodecs().maxInMemorySize(16 * 1024 * 1024))
-                        .build())
-                .build();
-    }
-
-    @Override
-    public AiTypeEnum getType() {
-        return AiTypeEnum.zhiPu;
-    }
-
-    @Override
-    public Flux<ServerSentEvent<String>> requestAi(String text) {
-        checkParam(text, aiProperties.getModel(), aiProperties.getApiKey());
-        OpenAiRequestParamDTO zhiPuRequestParamDTO = OpenAiRequestParamDTO.builder()
-                .model(aiProperties.getModel())
-                //sse
-                .stream(Boolean.TRUE)
-                .maxTokens(AiConstants.ZhiPuConstants.MAX_TOKENS)
-                .temperature(AiConstants.ZhiPuConstants.TEMPERATURE)
-                .messages(List.of(new AiMessage(AiConstants.ZhiPuConstants.REQUEST_ROLE, text)))
-                .build();
-
-        return webClient.post()
-                .body(BodyInserters.fromValue(zhiPuRequestParamDTO))
-                .retrieve()
-                .bodyToFlux(String.class)
-                .filter(aiResponse -> !"[DONE]".equals(aiResponse))
-                .map(OpenAiResponse::convertToResponse)
-                .doOnError(error -> log.info("ZhiPuServiceImpl.requestAi exception:{}", error.getMessage()));
-    }
-
-    private void checkParam(String param, String model, String apiKey) {
-        Assert.notNull(param, "text is null");
-        Assert.notNull(model, "model is null");
-        Assert.notNull(apiKey, "ai.api-key is null");
-    }
-
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/factory/AiServiceFactoryImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/factory/AiServiceFactoryImpl.java
deleted file mode 100644
index 8e0954c7ad..0000000000
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/ai/factory/AiServiceFactoryImpl.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.hertzbeat.manager.service.ai.factory;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import javax.annotation.PostConstruct;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.service.ai.AiService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.stereotype.Component;
-import org.springframework.util.Assert;
-import org.springframework.util.CollectionUtils;
-
-/**
- * AI bean factory
- */
-@Component
-@ConditionalOnProperty(prefix = "ai", name = "type")
-public class AiServiceFactoryImpl {
-
-    @Autowired(required = false)
-    private List<AiService> aiService;
-
-    private Map<AiTypeEnum, AiService> aiServiceFactoryMap = new HashMap<>();
-
-    @PostConstruct
-    public void init() {
-        if (CollectionUtils.isEmpty(aiService)) {
-            return;
-        }
-        aiServiceFactoryMap = aiService.stream()
-                .collect(Collectors.toMap(AiService::getType, Function.identity()));
-    }
-
-    public AiService getAiServiceImplBean(String type) {
-        Assert.notNull(type, "type is null");
-        AiTypeEnum typeByName = AiTypeEnum.getTypeByName(type);
-        Assert.notNull(typeByName, "The current type is not supported,please check that your type value is consistent with the documentation on the website");
-        AiService aiServiceImpl = aiServiceFactoryMap.get(typeByName);
-        Assert.notNull(aiServiceImpl, "No bean for current type found");
-        return aiServiceImpl;
-    }
-
-}
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MailGeneralConfigServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MailGeneralConfigServiceImpl.java
index ffc180451b..a1a4c3cc5e 100644
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MailGeneralConfigServiceImpl.java
+++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/MailGeneralConfigServiceImpl.java
@@ -22,7 +22,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import java.lang.reflect.Type;
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
-import org.apache.hertzbeat.alert.dto.MailServerConfig;
+import org.apache.hertzbeat.common.entity.dto.MailServerConfig;
 import org.springframework.stereotype.Service;
 
 /**
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/ModelProviderConfigServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/ModelProviderConfigServiceImpl.java
index 22d93909d8..160c2b921d 100644
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/ModelProviderConfigServiceImpl.java
+++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/ModelProviderConfigServiceImpl.java
@@ -20,7 +20,7 @@ package org.apache.hertzbeat.manager.service.impl;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.lang.reflect.Type;
-import org.apache.hertzbeat.ai.pojo.dto.ModelProviderConfig;
+import org.apache.hertzbeat.common.entity.dto.ModelProviderConfig;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
 import org.apache.hertzbeat.common.support.event.AiProviderConfigChangeEvent;
diff --git a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/SmsGeneralConfigServiceImpl.java b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/SmsGeneralConfigServiceImpl.java
index 648550712f..1e39e2695c 100644
--- a/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/SmsGeneralConfigServiceImpl.java
+++ b/hertzbeat-manager/src/main/java/org/apache/hertzbeat/manager/service/impl/SmsGeneralConfigServiceImpl.java
@@ -22,9 +22,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import java.lang.reflect.Type;
 
 import jakarta.annotation.Resource;
-import org.apache.hertzbeat.alert.config.SmsConfig;
+
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
+import org.apache.hertzbeat.common.entity.dto.sms.SmsConfig;
 import org.apache.hertzbeat.common.support.event.SmsConfigChangeEvent;
 import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Service;
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/AiControllerTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/AiControllerTest.java
deleted file mode 100644
index e615953246..0000000000
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/AiControllerTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.hertzbeat.manager.controller;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.when;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-import org.apache.hertzbeat.manager.config.AiProperties;
-import org.apache.hertzbeat.manager.service.ai.AiService;
-import org.apache.hertzbeat.manager.service.ai.factory.AiServiceFactoryImpl;
-import org.junit.jupiter.api.BeforeEach;
-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 org.springframework.http.MediaType;
-import org.springframework.http.codec.ServerSentEvent;
-import org.springframework.test.web.servlet.MockMvc;
-import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
-import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import reactor.core.publisher.Flux;
-
-/**
- * test case for {@link AiController}
- */
-
-@ExtendWith(MockitoExtension.class)
-class AiControllerTest {
-
-    private MockMvc mockMvc;
-
-    @Mock
-    private AiServiceFactoryImpl aiServiceFactory;
-
-    @Mock
-    private AiProperties aiProperties;
-
-    @Mock
-    private AiService aiService;
-
-    @InjectMocks
-    private AiController aiController;
-
-    @BeforeEach
-    public void setup() {
-
-        mockMvc = MockMvcBuilders.standaloneSetup(aiController).build();
-    }
-
-    @Test
-    public void testRequestAi() throws Exception {
-
-        String responseText = "response";
-        Flux<ServerSentEvent<String>> responseFlux = Flux.just(ServerSentEvent.builder(responseText).build());
-
-        when(aiServiceFactory.getAiServiceImplBean(anyString())).thenReturn(aiService);
-        when(aiService.requestAi(anyString())).thenReturn(responseFlux);
-        when(aiProperties.getType()).thenReturn("alibabaAi");
-
-        String requestBody = "{\"text\":\"Who are you\"}";
-
-        mockMvc.perform((MockMvcRequestBuilders.post("/api/ai/get")
-                .content(requestBody)
-                .contentType(MediaType.APPLICATION_JSON)
-                .accept(MediaType.TEXT_EVENT_STREAM)))
-                .andExpect(status().isOk())
-                .andExpect(content().contentType(MediaType.TEXT_EVENT_STREAM_VALUE))
-                .andExpect(content().string("data:response\n\n"));
-    }
-
-}
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MetricsFavoriteControllerTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MetricsFavoriteControllerTest.java
index dad6f7d245..3be38dcb15 100644
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MetricsFavoriteControllerTest.java
+++ b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/controller/MetricsFavoriteControllerTest.java
@@ -252,4 +252,4 @@ class MetricsFavoriteControllerTest {
             verify(metricsFavoriteService, never()).addMetricsFavorite(anyString(), anyLong(), anyString());
         }
     }
-}
\ No newline at end of file
+}
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/AiServiceFactoryTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/AiServiceFactoryTest.java
deleted file mode 100644
index 60f5e627d6..0000000000
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/AiServiceFactoryTest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.hertzbeat.manager.service;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.when;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import org.apache.hertzbeat.common.constants.AiTypeEnum;
-import org.apache.hertzbeat.manager.service.ai.AiService;
-import org.apache.hertzbeat.manager.service.ai.factory.AiServiceFactoryImpl;
-import org.junit.jupiter.api.BeforeEach;
-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 org.springframework.test.util.ReflectionTestUtils;
-
-/**
- * test case for {@link AiServiceFactoryImpl}
- */
-
-@ExtendWith(MockitoExtension.class)
-class AiServiceFactoryTest {
-
-    @Mock
-    private List<AiService> aiService;
-
-    @Mock
-    private AiService aiService1;
-
-    @Mock
-    private AiService aiService2;
-
-    @InjectMocks
-    private AiServiceFactoryImpl aiServiceFactory;
-
-    @BeforeEach
-    public void setup() {
-
-        when(aiService1.getType()).thenReturn(AiTypeEnum.alibabaAi);
-        when(aiService2.getType()).thenReturn(AiTypeEnum.zhiPu);
-
-        aiService = Arrays.asList(aiService1, aiService2);
-        ReflectionTestUtils.setField(aiServiceFactory, "aiService", aiService);
-
-        aiServiceFactory.init();
-    }
-
-    @Test
-    public void testInit() {
-
-        Map<AiTypeEnum, AiService> expectedMap = aiService.stream()
-                .collect(Collectors.toMap(AiService::getType, Function.identity()));
-
-        Map<AiTypeEnum, AiService> actualMap = (Map<AiTypeEnum, AiService>) ReflectionTestUtils.getField(aiServiceFactory, "aiServiceFactoryMap");
-
-        assertEquals(expectedMap, actualMap);
-    }
-
-    @Test
-    public void testGetAiServiceImplBean_Success() {
-
-        AiService service = aiServiceFactory.getAiServiceImplBean(AiTypeEnum.alibabaAi + "");
-        assertNotNull(service);
-        assertEquals(aiService1, service);
-
-        service = aiServiceFactory.getAiServiceImplBean(AiTypeEnum.zhiPu + "");
-        assertNotNull(service);
-        assertEquals(aiService2, service);
-    }
-
-    @Test
-    public void testGetAiServiceImplBeanTypeNotFound() {
-
-        Exception exception = assertThrows(
-                IllegalArgumentException.class,
-                () -> aiServiceFactory.getAiServiceImplBean("InvalidType")
-        );
-
-        assertTrue(exception.getMessage().contains("The current type is not supported"));
-    }
-
-    @Test
-    public void testGetAiServiceImplBeanNoBean() {
-
-        aiServiceFactory.init();
-
-        when(aiService1.getType()).thenReturn(AiTypeEnum.kimiAi);
-        List<AiService> singleServiceList = Collections.singletonList(aiService1);
-        ReflectionTestUtils.setField(aiServiceFactory, "aiService", singleServiceList);
-        aiServiceFactory.init();
-
-        Exception exception = assertThrows(
-                IllegalArgumentException.class,
-                () -> aiServiceFactory.getAiServiceImplBean(AiTypeEnum.sparkDesk + "")
-        );
-
-        assertTrue(exception.getMessage().contains("No bean for current type found"));
-    }
-
-}
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/ConfigServiceTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/ConfigServiceTest.java
index b86a69c677..ea43185b0f 100644
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/ConfigServiceTest.java
+++ b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/ConfigServiceTest.java
@@ -27,7 +27,7 @@ import java.util.ArrayList;
 import java.util.List;
 import org.apache.hertzbeat.base.service.GeneralConfigService;
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
-import org.apache.hertzbeat.alert.dto.MailServerConfig;
+import org.apache.hertzbeat.common.entity.dto.MailServerConfig;
 import org.apache.hertzbeat.manager.pojo.dto.ObjectStoreDTO;
 import org.apache.hertzbeat.manager.pojo.dto.TemplateConfig;
 import org.apache.hertzbeat.manager.service.impl.ConfigServiceImpl;
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/KimiAiServiceTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/KimiAiServiceTest.java
deleted file mode 100644
index a747c6f2ad..0000000000
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/KimiAiServiceTest.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.hertzbeat.manager.service;
-
-
-import org.apache.hertzbeat.manager.service.ai.KimiAiServiceImpl;
-
-/**
- * test case for {@link KimiAiServiceImpl}
- */
-
-class KimiAiServiceTest {
-}
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MailGeneralConfigServiceTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MailGeneralConfigServiceTest.java
index 0d6b0ff29d..7ea204d394 100644
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MailGeneralConfigServiceTest.java
+++ b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/MailGeneralConfigServiceTest.java
@@ -22,7 +22,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
-import org.apache.hertzbeat.alert.dto.MailServerConfig;
+import org.apache.hertzbeat.common.entity.dto.MailServerConfig;
 import org.apache.hertzbeat.manager.service.impl.MailGeneralConfigServiceImpl;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/SmsGeneralConfigServiceTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/SmsGeneralConfigServiceTest.java
index 6845936b88..e8aada1dd8 100644
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/SmsGeneralConfigServiceTest.java
+++ b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/SmsGeneralConfigServiceTest.java
@@ -21,9 +21,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.hertzbeat.alert.config.SmsConfig;
 import org.apache.hertzbeat.common.constants.GeneralConfigTypeEnum;
 import org.apache.hertzbeat.base.dao.GeneralConfigDao;
+import org.apache.hertzbeat.common.entity.dto.sms.SmsConfig;
 import org.apache.hertzbeat.manager.service.impl.SmsGeneralConfigServiceImpl;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
diff --git a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/ZhiPuServiceTest.java b/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/ZhiPuServiceTest.java
deleted file mode 100644
index 12fb3fd10b..0000000000
--- a/hertzbeat-manager/src/test/java/org/apache/hertzbeat/manager/service/ZhiPuServiceTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.hertzbeat.manager.service;
-
-import org.apache.hertzbeat.manager.service.ai.ZhiPuServiceImpl;
-
-/**
- * test case for {@link ZhiPuServiceImpl}
- */
-
-class ZhiPuServiceTest {
-}
diff --git a/hertzbeat-startup/pom.xml b/hertzbeat-startup/pom.xml
index 1781f4835b..f45a196a6b 100644
--- a/hertzbeat-startup/pom.xml
+++ b/hertzbeat-startup/pom.xml
@@ -87,6 +87,12 @@
             <artifactId>hertzbeat-remoting</artifactId>
         </dependency>
 
+        <!-- HertzBeat ai -->
+        <dependency>
+            <groupId>org.apache.hertzbeat</groupId>
+            <artifactId>hertzbeat-ai</artifactId>
+        </dependency>
+
         
         <!-- Jackson -->
         <dependency>
diff --git a/home/README.md b/home/README.md
index ecf5e70e55..35b7eaf9f4 100644
--- a/home/README.md
+++ b/home/README.md
@@ -60,9 +60,9 @@ This command generates static content into the `build` directory and can be serv
 ## Deployment
 
 ```console
-GIT_USER=<Your GitHub username> USE_SSH=true pnpm deploy
+GIT_USER=<Your GitHub username> USE_SSH=true pnpm run deploy
 OR
-USE_SSH=true pnpm deploy
+USE_SSH=true pnpm run deploy
 ```
 
 If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
@@ -70,7 +70,7 @@ If you are using GitHub pages for hosting, this command is a convenient way to b
 ### Deployment to Gitee
 
 ```console
-GITHUB_HOST=gitee.com USE_SSH=true pnpm deploy
+GITHUB_HOST=gitee.com USE_SSH=true pnpm run deploy
 ```
 
 ### Archive Version
diff --git a/home/docs/help/ai_agent_chat.md b/home/docs/help/ai_agent.md
similarity index 91%
rename from home/docs/help/ai_agent_chat.md
rename to home/docs/help/ai_agent.md
index 66e6413a6a..9607c5ce66 100644
--- a/home/docs/help/ai_agent_chat.md
+++ b/home/docs/help/ai_agent.md
@@ -1,15 +1,15 @@
 ---
-id: ai_agent_chat
-title: AI Agent Chat User Guide
-sidebar_label: AI Agent Chat
+id: ai_agent
+title: HertzBeat AI Agent User Guide
+sidebar_label: HertzBeat AI
 keywords: [AI, Chat, Agent, Monitoring, AI Agent, OpenAI]
 ---
 
-> HertzBeat AI Agent Chat is an intelligent monitoring AI Agent that helps you manage monitors, configure alerts, and optimize your infrastructure monitoring through natural language conversation.
+> HertzBeat AI Agent is an intelligent monitoring AI Agent that helps you manage monitors, configure alerts, and optimize your infrastructure monitoring through natural language conversation.
 
 ## Overview
 
-The AI Agent Chat feature provides an interactive chat interface where you can:
+The HertzBeat AI Agent feature provides an interactive chat interface where you can:
 
 **Monitor Management:**
 
@@ -40,7 +40,7 @@ The AI Agent Chat feature provides an interactive chat interface where you can:
 
 ## Prerequisites
 
-Before using the AI Agent Chat, ensure:
+Before using the AI Agent, ensure:
 
 1 **OpenAI Configuration**: Valid OpenAI API key must be configured. Optionally, you can change the model in `application.yml` under `spring.ai.openai.chat.options.model` (default is `gpt-4.1-nano`).
 2 **Database Connection**: HertzBeat database must be accessible for monitor operations
@@ -49,37 +49,26 @@ Before using the AI Agent Chat, ensure:
 
 ### OpenAI API Key Setup
 
-The AI Agent Chat uses OpenAI's GPT models. You need to configure an OpenAI API key in one of two ways:
+The AI Agent uses OpenAI's GPT models. You need to configure an OpenAI API key in this ways:
 
-#### Method 1: Database Configuration via UI (Recommended)
+#### Database Configuration via UI
 
-1. Navigate to the AI Agent Chat interface
+1. Navigate to the AI Agent interface
 2. If no API key is configured, you'll see a configuration dialog
 3. Enter your OpenAI API key
 4. Click **Save Configuration**
 
-#### Method 2: YAML Configuration
-
-Add to your `application.yml`:
-
-```yaml
-spring:
-  ai:
-    openai:
-      api-key: sk-your-openai-api-key-here
-```
-
 ### Configuration Priority
 
 - **Database configuration** takes priority over YAML configuration
 - Configuration changes are applied immediately without restart
 - Invalid API keys are automatically validated before saving
 
-## Using the AI Agent Chat
+## Using the AI Agent
 
 ### Accessing the Chat Interface
 
-1. Navigate to the **AI Agent Chat** section in HertzBeat web interface
+1. Navigate to the **AI Agent** section in HertzBeat web interface
 2. You'll see the HertzBeat Monitoring AI Agent welcome screen
 3. Start typing your questions in the chat input field
 
@@ -361,7 +350,7 @@ You: Add HTTP monitors for all services in my staging environment:
 
 ## Support
 
-For issues with AI Agent Chat:
+For issues with AI Agent:
 
 1. Check this documentation first
 2. Review application logs for errors
diff --git a/home/docs/help/ai_config.md b/home/docs/help/ai_config.md
deleted file mode 100644
index fe2e79f231..0000000000
--- a/home/docs/help/ai_config.md
+++ /dev/null
@@ -1,81 +0,0 @@
----
-id: ai_config
-title: AI QuickStart  
-sidebar_label: AI QuickStart
-keywords: [AI]
----
-
-> The dialogue with artificial intelligence is achieved by configuring aiConfig in the application.yml file
-
-### Configuration parameter description
-
-| Name of the parameter |                      Parameter help description                       |
-|-----------------------|-----------------------------------------------------------------------|
-| type                  | Choose a large AI model (such as Zhipu, Tongyi thousand questions...) |
-| model                 | Select the model, which defaults to GLM-4                             |
-| api-key               | Gets the api_key, without which you cannot talk to the large model    |
-
-### Large model options and configuration details
-
-#### ZhiPu AI
-
-| Name of the parameter |                       Example                       |                              Link                               |
-|-----------------------|-----------------------------------------------------|-----------------------------------------------------------------|
-| type                  | zhiPu (must be exactly the same as example)         |                                                                 |
-| model                 | glm-4-0520、glm-4 、glm-4-air、glm-4-airx、 glm-4-flash |                                                                 |
-| api-key               | xxxxx.xxxxxx                                        | <https://open.bigmodel.cn/login?redirect=%2Fusercenter%2Fapikeys> |
-
-#### Alibaba AI
-
-| Name of the parameter |                                           Example                                            |                                                            Link                                                            |
-|-----------------------|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
-| type                  | alibabaAi (must be exactly the same as example)                                              |                                                                                                                            |
-| model                 | qwen-turbo、qwen-plus、qwen-max、qwen-max-0428、qwen-max-0403、qwen-max-0107、qwen-max-longcontext | <https://help.aliyun.com/zh/dashscope/developer-reference/model-introduction?spm=a2c4g.11186623.0.0.4e0246c1RQFKMH>          |
-| api-key               | xxxxxxxxxxx                                                                                  | <https://help.aliyun.com/zh/dashscope/developer-reference/activate-dashscope-and-create-an-api-key?spm=a2c4g.11186623.0.i10> |
-
-#### Kimi AI
-
-| Name of the parameter |                     Example                     |                     Link                      |
-|-----------------------|-------------------------------------------------|-----------------------------------------------|
-| type                  | kimiAi (must be exactly the same as example)    |                                               |
-| model                 | moonshot-v1-8k、moonshot-v1-32k、moonshot-v1-128k |                                               |
-| api-key               | xxxxxxxxxxx                                     | <https://platform.moonshot.cn/console/api-keys> |
-
-#### sparkDesk AI
-
-QuickStart: <https://www.xfyun.cn/doc/platform/quickguide.html>
-
-| Name of the parameter |                     Example                      |                 Link                  |
-|-----------------------|--------------------------------------------------|---------------------------------------|
-| type                  | sparkDesk (must be exactly the same as example)  |                                       |
-| model                 | general、generalv2、generalv3、generalv3.5、4.0Ultra |                                       |
-| api-key               | xxxxxxxxxxx                                      | <https://console.xfyun.cn/services/cbm> |
-| api-secret            | xxxxxxxxxxx                                      | <https://console.xfyun.cn/services/cbm> |
-
-| sparkDesk version |    model    |
-|-------------------|-------------|
-| Spark4.0 Ultra    | 4.0Ultra    |
-| Spark Max         | generalv3.5 |
-| Spark Pro         | generalv3   |
-| Spark V2.0        | generalv2   |
-| Spark Lite(free)  | general     |
-
-#### Ollama AI
-
-QuickStart: <https://github.com/ollama/ollama/tree/main/docs>
-
-| Name of the parameter | Example                                         | Link                          |
-|-----------------------|-------------------------------------------------|-------------------------------|
-| type                  | ollama (must be exactly the same as example)    |                               |
-| model                 | deepseek-r1:latest、qwen3:latest、llama4:16x17b   | <https://ollama.com/search>   |
-| api-url               | <http://127.0.0.1:11434/v1/chat/completions>    |                               |
-
-#### OpenRouter
-
-QuickStart: <https://openrouter.ai/docs/quickstart>
-
-| Name of the parameter | Example                                        | Link                                    |
-|-----------------------|------------------------------------------------|-----------------------------------------|
-| type                  | openRouter (must be exactly the same as example) |                                       |
-| model                 | openai/gpt-4o, anthropic/claude-sonnet-4       | <https://openrouter.ai/models>          |
-| api-key               | xxxxxxxxxxx                                    | <https://openrouter.ai/settings/provisioning-keys> |
diff --git a/home/docs/help/mcp_sse_server.md b/home/docs/help/mcp_sse_server.md
index fed675062d..0b600e70a4 100644
--- a/home/docs/help/mcp_sse_server.md
+++ b/home/docs/help/mcp_sse_server.md
@@ -1,7 +1,7 @@
 ---
 id: mcp_sse_server
-title: MCP SSE Server
-sidebar_label: MCP SSE Server
+title: MCP Server
+sidebar_label: MCP Server
 keywords: [MCP, SSE, streaming, server]
 ---
 
@@ -26,6 +26,8 @@ You must authenticate each request using one of the following methods:
 
   - Header: `Authorization: Bearer <your-jwt-token>`
 
+Note: You can generate a JWT token from the HertzBeat web UI under the Log Integration or Alarm Integration Page.
+
 - Basic authentication
   - Header: `Authorization: Basic <base64(username:password)>`
 
diff --git a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/ai_agent.md b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/ai_agent.md
new file mode 100644
index 0000000000..9def604995
--- /dev/null
+++ b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/ai_agent.md
@@ -0,0 +1,357 @@
+---
+id: ai_agent
+title: HertzBeat AI 智能助手用户指南
+sidebar_label: HertzBeat AI
+keywords: [AI, 聊天, 智能助手, 监控, AI Agent, OpenAI]
+---
+
+> HertzBeat AI 智能助手是一个智能监控 AI 助手,通过自然语言对话帮助您管理监控器、配置告警并优化基础设施监控。
+
+## 概述
+
+HertzBeat AI 智能助手功能提供了一个交互式聊天界面,您可以:
+
+**监控器管理:**
+
+- 🔍 按状态、类型、主机和标签查询和过滤现有监控器
+- ➕ 为网站、API、数据库和服务添加新的监控器
+- 📊 获取可用监控器类型及其参数的详细信息
+- ⚡ 检查监控器状态并排除监控问题
+
+**告警管理:**
+
+- 🚨 通过综合过滤(类型、状态、搜索)查询活跃告警
+- 📈 获取告警摘要统计和分布
+- 🔔 查看单个和分组告警
+- 📋 分析告警模式和趋势
+
+**指标分析:**
+
+- 📊 检索任何监控器的实时指标数据
+- 📈 访问可自定义时间范围的历史指标
+- 💾 检查仓库存储系统状态
+- 🔍 查询特定指标字段和标签
+
+**告警规则管理:**
+
+- ⚙️ 配置告警规则和阈值
+- 📝 管理不同监控器类型的告警定义
+- 🎯 设置自定义告警条件
+
+## 先决条件
+
+在使用 AI 智能助手之前,请确保:
+
+1. **OpenAI 配置**:必须配置有效的 OpenAI API 密钥。可选地,您可以在 `application.yml` 中的 `spring.ai.openai.chat.options.model` 下更改模型(默认为 `gpt-4.1-nano`)。
+2. **数据库连接**:HertzBeat 数据库必须可访问以进行监控器操作
+
+## 配置
+
+### OpenAI API 密钥设置
+
+AI 智能助手使用 OpenAI 的 GPT 模型。您需要通过以下方式配置 OpenAI API 密钥:
+
+#### 通过 UI 进行数据库配置
+
+1. 导航到 AI 智能助手界面
+2. 如果未配置 API 密钥,您将看到配置对话框
+3. 输入您的 OpenAI API 密钥
+4. 点击 **保存配置**
+
+### 配置优先级
+
+- **数据库配置** 优先于 YAML 配置
+- 配置更改立即生效,无需重启
+- 保存前会自动验证无效的 API 密钥
+
+## 使用 AI 智能助手
+
+### 访问聊天界面
+
+1. 在 HertzBeat Web 界面中导航到 **AI 智能助手** 部分
+2. 您将看到 HertzBeat 监控 AI 助手欢迎屏幕
+3. 在聊天输入框中开始输入您的问题
+
+### 示例对话
+
+#### 添加新监控器
+
+```text
+您:为我的网站 https://example.com 添加一个新的 HTTP 监控器
+AI 助手:我将帮助您为 https://example.com 添加一个 HTTP 监控器。
+让我使用以下配置创建该监控器:
+- 名称:example.com 网站监控器
+- 类型:HTTP
+- 主机:example.com
+- 端口:443 (HTTPS)
+- 路径:/
+- 间隔:60 秒
+
+监控器创建成功,ID:12345
+```
+
+#### 列出现有监控器
+
+```text
+您:显示我所有当前的监控器
+AI 助手:以下是您当前的监控器:
+
+1. **Linux 服务器** (ID: 1001)
+   - 状态:✅ 在线
+   - 主机:192.168.1.100
+   - 最后检查:2 分钟前
+
+2. **MySQL 数据库** (ID: 1002) 
+   - 状态:⚠️ 警告
+   - 主机:db.example.com
+   - 最后检查:30 秒前
+
+3. **网站监控器** (ID: 1003)
+   - 状态:✅ 在线
+   - 主机:https://example.com
+   - 最后检查:1 分钟前
+
+您想了解任何特定监控器的详细信息吗?
+```
+
+#### 获取监控器类型信息
+
+```text
+您:监控 PostgreSQL 数据库需要哪些参数?
+AI 助手:要监控 PostgreSQL 数据库,您需要这些参数:
+
+**必需参数:**
+- **主机**:数据库服务器 IP/主机名
+- **端口**:PostgreSQL 端口(默认:5432)
+- **数据库**:要连接的数据库名称
+- **用户名**:数据库用户名
+- **密码**:数据库密码
+
+**可选参数:**
+- **超时**:连接超时(默认:6000ms)
+- **查询超时**:SQL 查询超时(默认:3000ms)
+- **SSL**:启用 SSL 连接(默认:false)
+
+您想让我帮助您添加一个 PostgreSQL 监控器吗?
+```
+
+#### 告警管理
+
+```text
+您:显示过去 24 小时内的所有严重告警
+AI 助手:以下是过去 24 小时内的严重告警:
+
+🚨 **活跃告警(3 个触发中)**
+1. **高 CPU 使用率** - Linux 服务器 (ID: 1001)
+   - 状态:🔥 触发中
+   - 触发时间:2 小时前
+   - 严重程度:严重
+   - 消息:CPU 使用率 95% > 阈值 90%
+
+2. **数据库连接失败** - MySQL 数据库 (ID: 1002)
+   - 状态:🔥 触发中
+   - 触发时间:45 分钟前
+   - 严重程度:严重
+   - 消息:10 秒后连接超时
+
+3. **网站响应时间** - 网站监控器 (ID: 1003)
+   - 状态:⚠️ 警告
+   - 触发时间:15 分钟前
+   - 严重程度:警告
+   - 消息:响应时间 5.2s > 阈值 3s
+
+**告警摘要:**
+- 总告警数:12
+- 触发中:3(2 个严重,1 个警告)
+- 已解决:9
+
+您想让我帮助调查任何特定的告警吗?
+```
+
+#### 指标分析
+
+```text
+您:显示我的 Linux 服务器过去 6 小时的 CPU 使用率
+AI 助手:以下是您的 Linux 服务器(监控器 ID:1001)过去 6 小时的 CPU 使用率数据:
+
+📊 **CPU 使用率指标 - 过去 6 小时**
+
+时间          | 使用率 (%) | 负载平均 | 进程数
+14:00-15:00   | 45.2%     | 1.2      | 156
+15:00-16:00   | 67.8%     | 2.1      | 178
+16:00-17:00   | 89.4%     | 3.8      | 195
+17:00-18:00   | 92.1%     | 4.2      | 203
+18:00-19:00   | 94.7%     | 4.8      | 210
+19:00-20:00   | 88.3%     | 3.5      | 188
+
+**分析:**
+- 峰值使用率:19:00 时 94.7%
+- 平均使用率:79.6%
+- 趋势:高使用率持续 3+ 小时
+- 当前状态:下降中(88.3%)
+
+**实时指标:**
+- 当前 CPU:76.2%
+- 内存使用率:82.1%
+- 磁盘 I/O:正常
+
+您想让我检查历史数据进行比较或调查高使用率的原因吗?
+```
+
+#### 告警规则配置
+
+```text
+您:当我的网站响应时间超过 5 秒时设置告警规则
+AI 助手:我将帮助您创建网站响应时间监控的告警规则。
+
+**告警规则配置:**
+- **监控器类型**:HTTP/网站
+- **指标**:响应时间
+- **条件**:大于 5 秒
+- **严重程度**:警告
+- **评估**:每 60 秒检查一次
+- **通知**:邮件 + 仪表板
+
+**建议规则:**
+```yaml
+name: "网站响应时间告警"
+condition: "response_time > 5000ms"
+severity: "warning"
+description: "当网站响应时间超过 5 秒时告警"
+evaluation_interval: 60s
+for: 2m  # 条件持续 2 分钟后告警
+```
+
+此规则将:
+
+1. 每分钟监控响应时间
+2. 如果响应时间 > 5s 持续 2+ 分钟则触发告警
+3. 通过配置的渠道发送通知
+4. 在仪表板中显示警告状态
+
+您想让我应用此配置还是修改任何设置?
+
+``` text
+
+### 聊天功能
+
+#### 消息历史
+
+- 所有对话都会自动保存
+- 从侧边栏访问以前的对话
+- 搜索对话历史
+- 导出对话日志
+
+#### 实时响应
+
+- 流式响应提供即时反馈
+- 输入指示器显示助手正在处理时
+- 如需要可取消正在进行的请求
+
+#### 对话管理
+
+- 为不同主题创建新对话
+- 重命名对话以便更好地组织
+- 删除旧对话以保持整洁
+注意:对话不会保存在数据库中
+
+## 故障排除
+
+### 常见问题
+
+#### 聊天界面无法加载
+
+**症状**:聊天界面无限显示加载旋转器
+**解决方案**:
+
+1. 检查浏览器控制台中的 JavaScript 错误
+2. 确保与 HertzBeat 服务器的网络连接
+
+#### "服务不可用"消息
+
+**症状**:聊天显示"HertzBeat AI 监控服务不可用"
+**解决方案**:
+1. 验证 OpenAI API 密钥配置
+2. 检查应用程序日志中的错误
+3. 确保数据库连接
+
+#### 无效 API 密钥错误
+
+**症状**:配置对话框显示"无效 API 密钥"错误
+**解决方案**:
+
+1. 验证您的 OpenAI API 密钥以 `sk-` 开头
+2. 检查 API 密钥是否有足够的积分/配额
+3. 直接使用 OpenAI API 测试 API 密钥
+4. 确保 API 密钥中没有多余的空格
+
+#### 监控器创建失败
+
+**症状**:AI 建议监控器配置但创建失败
+**解决方案**:
+
+1. 验证您有创建监控器的权限
+2. 检查是否已存在同名监控器
+3. 确保目标主机/服务可访问
+4. 查看监控器参数验证错误
+
+### 调试模式
+
+通过设置日志级别为 DEBUG 来启用调试日志:
+
+```yaml
+logging:
+  level:
+    org.apache.hertzbeat.ai.agent: DEBUG
+```
+
+## 最佳实践
+
+### 有效的聊天使用
+
+1. **具体明确**:"为 api.example.com 端口 8080 添加 HTTP 监控器" vs "添加一个监控器"
+2. **提供上下文**:说明您想要生产环境还是测试环境监控器
+3. **询问后续问题**:如需要请求配置详细信息
+4. **使用自然语言**:AI 理解对话式请求
+
+### 监控器管理
+
+1. **命名约定**:使用描述性的监控器名称
+2. **文档记录**:要求 AI 记录复杂配置
+
+### 安全考虑
+
+1. **API 密钥安全**:安全存储 OpenAI API 密钥
+2. **访问控制**:限制 AI 聊天访问给授权用户
+3. **数据隐私**:注意聊天日志中的敏感信息
+4. **网络安全**:确保与 OpenAI API 的安全连接
+
+## 高级功能
+
+### 批量操作
+
+```text
+您:为我的预发布环境中的所有服务添加 HTTP 监控器:
+- api-staging.example.com:8080
+- web-staging.example.com:80  
+- admin-staging.example.com:3000
+```
+
+## 限制
+
+- 需要活跃的互联网连接访问 OpenAI API
+- OpenAI API 使用会根据令牌消耗产生费用
+- 复杂的多步骤操作可能需要多次交互
+- 某些高级配置可能需要手动设置
+- 可能会根据 OpenAI 计划应用速率限制
+
+## 支持
+
+对于 AI 智能助手的问题:
+
+1. 首先查看此文档
+2. 查看应用程序日志中的错误
+3. 独立测试 OpenAI API 连接
+4. 联系 HertzBeat 支持并提供具体错误消息
+
+---
diff --git a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/ai_config.md b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/ai_config.md
deleted file mode 100644
index ed59d6f764..0000000000
--- a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/ai_config.md
+++ /dev/null
@@ -1,81 +0,0 @@
----
-id: ai_config
-title: AI 快速入门  
-sidebar_label: AI 快速入门
-keywords: [人工智能 AI]
----
-
-> 通过配置application.yml文件里面的aiConfig实现与人工智能的对话
-
-### 配置参数说明
-
-|  参数名称   |            参数帮助描述            |
-|---------|------------------------------|
-| type    | 选择AI大模型(如智普、通义千问...)         |
-| model   | 选择模型,默认为GLM-4                |
-| api-key | 获取api_key,如果没有该配置,无法与大模型进行对话 |
-
-### 大模型选项与配置详解
-
-#### 智普AI
-
-|  参数名称   |                         示例                          |                               链接                                |
-|---------|-----------------------------------------------------|-----------------------------------------------------------------|
-| type    | zhiPu(必须和示例完全相同)                                    | 无                                                               |
-| model   | glm-4-0520、glm-4 、glm-4-air、glm-4-airx、 glm-4-flash | 无                                                               |
-| api-key | xxxxx.xxxxxx                                        | <https://open.bigmodel.cn/login?redirect=%2Fusercenter%2Fapikeys> |
-
-#### 阿里巴巴AI
-
-|  参数名称   |                                              示例                                              |                                                             链接                                                             |
-|---------|----------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|
-| type    | alibabaAi(必须和示例完全相同)                                                                         | 无                                                                                                                          |
-| model   | qwen-turbo、qwen-plus、qwen-max、qwen-max-0428、qwen-max-0403、qwen-max-0107、qwen-max-longcontext | <https://help.aliyun.com/zh/dashscope/developer-reference/model-introduction?spm=a2c4g.11186623.0.0.4e0246c1RQFKMH>          |
-| api-key | xxxxxxxxxxx                                                                                  | <https://help.aliyun.com/zh/dashscope/developer-reference/activate-dashscope-and-create-an-api-key?spm=a2c4g.11186623.0.i10> |
-
-#### 月之暗面AI
-
-|  参数名称   |                       示例                        |                      链接                       |
-|---------|-------------------------------------------------|-----------------------------------------------|
-| type    | kimiAi(必须和示例完全相同)                               | 无                                             |
-| model   | moonshot-v1-8k、moonshot-v1-32k、moonshot-v1-128k | 无                                             |
-| api-key | xxxxxxxxxxx                                     | <https://platform.moonshot.cn/console/api-keys> |
-
-#### 科大讯飞AI
-
-快速入门:<https://www.xfyun.cn/doc/platform/quickguide.html>
-
-|    参数名称    |                        示例                        |                  链接                   |
-|------------|--------------------------------------------------|---------------------------------------|
-| type       | sparkDesk (must be exactly the same as example)  |                                       |
-| model      | general、generalv2、generalv3、generalv3.5、4.0Ultra |                                       |
-| api-key    | xxxxxxxxxxx                                      | <https://console.xfyun.cn/services/cbm> |
-| api-secret | xxxxxxxxxxx                                      | <https://console.xfyun.cn/services/cbm> |
-
-|      模型版本       | 模型类型(application.yml的model参数) |
-|-----------------|-------------------------------|
-| Spark4.0 Ultra  | 4.0Ultra                      |
-| Spark Max       | generalv3.5                   |
-| Spark Pro       | generalv3                     |
-| Spark V2.0      | generalv2                     |
-| Spark Lite(免费版) | general                       |
-
-#### Ollama AI
-
-快速入门: <https://github.com/ollama/ollama/tree/main/docs>
-
-| 参数名称 |                     示例                      |                 链接                  |
-|-----------------------|--------------------------------------------------|---------------------------------------|
-| type                  | ollama (必须和示例完全相同)  |                                       |
-| model                 | deepseek-r1:latest、qwen3:latest、llama4:16x17b | <https://ollama.com/search> |
-| api-url               | <http://127.0.0.1:11434/v1/chat/completions> |                                  |
-
-#### OpenRouter
-
-快速入门: <https://openrouter.ai/docs/quickstart>
-
-| 参数名称    | 示例                                       | 链接                                                 |
-|---------|------------------------------------------|----------------------------------------------------|
-| type    | openRouter (必须和示例完全相同)                   |                                                    |
-| model   | openai/gpt-4o, anthropic/claude-sonnet-4 | <https://openrouter.ai/models>                     |
-| api-key | xxxxxxxxxxx                              | <https://openrouter.ai/settings/provisioning-keys> |
diff --git a/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_sse_server.md b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_sse_server.md
new file mode 100644
index 0000000000..7e260a5e4d
--- /dev/null
+++ b/home/i18n/zh-cn/docusaurus-plugin-content-docs/current/help/mcp_sse_server.md
@@ -0,0 +1,97 @@
+---
+id: mcp_sse_server
+title: MCP 服务器
+sidebar_label: MCP 服务器
+keywords: [MCP, SSE, 流式传输, 服务器]
+---
+
+本页面介绍如何连接到 HertzBeat MCP SSE 服务器。当您启动 HertzBeat 服务器时,MCP 服务器会自动在默认端口 1157 上启动。
+
+### 概述
+
+- 提供用于工具调用的服务器发送事件 (SSE) 流。
+- 专为 MCP 集成和消费流式事件的客户端而设计。
+
+### 连接到 MCP 服务器
+
+确保 HertzBeat 服务器已启动并正在运行。如果您使用的端口不是 1157,请相应地替换以下内容:
+
+- URL: `http://localhost:1157/api/sse`
+
+### 身份验证
+
+您必须使用以下方法之一对每个请求进行身份验证:
+
+- JWT Bearer 令牌
+
+  - 请求头: `Authorization: Bearer <your-jwt-token>`
+
+注意:您可以在 HertzBeat Web UI 的日志集成或告警集成页面点击生成 JWT 令牌。
+
+- 基本身份验证
+  - 请求头: `Authorization: Basic <base64(username:password)>`
+
+### Cursor MCP 配置
+
+在您的主目录或项目根目录中创建或编辑 `.cursor/mcp.json`。
+
+基本身份验证:
+
+```json
+{
+      "Hertzbeat-MCP": {
+            "url": "http://localhost:1157/api/sse",
+            "headers": {
+                  "Authorization": "Basic <base64(username:password)>"
+            }
+      }
+}
+```
+
+JWT Bearer:
+
+```json
+{
+      "Hertzbeat-MCP": {
+            "url": "http://localhost:1157/api/sse",
+            "headers": {
+                  "Authorization": "Bearer <your-jwt-token>"
+            }
+      }
+}
+```
+
+保存后,在 Cursor 中重新加载 MCP 或重启编辑器。
+
+### 可用工具
+
+#### 监控管理工具
+
+- **query_monitors**: 查询现有/已配置的监控器,支持全面的过滤、分页和状态概览。支持按 ID、类型、状态、主机、标签进行过滤和排序。
+- **add_monitor**: 向 HertzBeat 添加新的监控目标,支持全面配置。处理每种监控器类型的不同参数要求。
+- **list_monitor_types**: 列出所有可添加到 HertzBeat 的监控器类型。显示所有支持的监控器类型及其显示名称。
+- **get_monitor_additional_params**: 获取特定监控器类型所需的参数定义。显示添加监控器时需要的参数。
+
+#### 指标数据工具
+
+- **query_realtime_metrics**: 获取特定监控器的实时指标数据。返回当前指标值,包括 CPU、内存、磁盘使用率等。
+- **get_historical_metrics**: 获取用于分析和趋势的历史指标数据。返回指定时间范围内指定指标的时间序列数据。
+- **get_warehouse_status**: 检查指标存储仓库系统的状态。返回指标存储是否可操作和可访问。
+
+#### 告警管理工具
+
+- **query_alerts**: 查询告警,支持全面的过滤和分页选项。支持按告警类型(单个/组)、状态(触发/已解决)、搜索词进行过滤和排序。
+- **get_alerts_summary**: 获取告警摘要统计信息,包括总数、状态分布和所有监控器的优先级分解。
+
+#### 告警规则定义工具
+
+- **create_alert_rule**: 基于应用层次结构和用户需求创建 HertzBeat 告警规则。支持阈值、字段条件和全面的告警配置。
+- **list_alert_rules**: 列出现有的告警规则,支持过滤选项。显示已配置的阈值和告警定义,支持搜索和分页。
+- **get_alert_rule_details**: 获取特定告警规则的详细信息。显示完整的阈值配置和规则设置。
+- **toggle_alert_rule**: 启用或禁用告警规则。允许激活或停用特定规则的阈值监控。
+- **get_apps_metrics_hierarchy**: 获取所有可用应用及其指标的层次结构,用于告警规则创建。返回带有字段参数的结构化 JSON 数据。
+- **bind_monitors_to_alert_rule**: 将监控器绑定到告警规则。将特定监控器与告警规则关联以启用监控和告警。
+
+### 注意事项
+
+- 如果连接断开,请使用相同的请求头重新连接。
diff --git a/home/sidebars.json b/home/sidebars.json
index e5ab4b430d..ed742d35d8 100755
--- a/home/sidebars.json
+++ b/home/sidebars.json
@@ -66,6 +66,8 @@
       "items": [
         "help/guide",
         "help/security_model",
+        "help/ai_agent",
+        "help/mcp_sse_server",
         {
           "type": "category",
           "label": "use-case",
@@ -287,10 +289,7 @@
         "help/plugin",
         "help/time_expression",
         "help/grafana_dashboard",
-        "help/mcp_sse_server",
         "help/collector",
-        "help/ai_agent_chat",
-        "help/ai_config",
         "help/risc-v",
         "help/issue"
       ]
diff --git a/pom.xml b/pom.xml
index 2155f2c2e3..ebc5972a50 100644
--- a/pom.xml
+++ b/pom.xml
@@ -202,6 +202,12 @@
                 <artifactId>hertzbeat-manager</artifactId>
                 <version>${hertzbeat.version}</version>
             </dependency>
+            <!-- ai -->
+            <dependency>
+                <groupId>org.apache.hertzbeat</groupId>
+                <artifactId>hertzbeat-ai</artifactId>
+                <version>${hertzbeat.version}</version>
+            </dependency>
             <!-- data warehouse -->
             <dependency>
                 <groupId>org.apache.hertzbeat</groupId>
diff --git a/script/application.yml b/script/application.yml
index e776cb9830..c4f4636014 100644
--- a/script/application.yml
+++ b/script/application.yml
@@ -19,6 +19,25 @@ spring:
     name: ${HOSTNAME:@hertzbeat@}${PID}
   profiles:
     active: prod
+  ai:
+    mcp:
+      server:
+        enabled: true
+        stdio: false
+        name: sse-mcp-server
+        version: 1.0.0
+        resource-change-notification: true
+        tool-change-notification: true
+        prompt-change-notification: true
+        sse-endpoint: /api/sse
+        sse-message-endpoint: /api/mcp/message
+        type: SYNC
+        capabilities:
+          tool: true
+          resource: true
+          prompt: true
+          completion: true
+
   mvc:
     static-path-pattern: /**
   jackson:
@@ -38,6 +57,7 @@ spring:
       max-file-size: 100MB
       max-request-size: 100MB
 
+
 management:
   health:
     mail:
@@ -124,13 +144,26 @@ spring:
 
 common:
   queue:
-    # memory or kafka
+    # memory, kafka, redis
     type: memory
     # properties when queue type is kafka
     kafka:
       servers: 127.0.0.1:9092
       metrics-data-topic: async-metrics-data
+      service-discovery-data-topic: service-discovery-data
       alerts-data-topic: async-alerts-data
+      log-entry-data-topic: async-log-entry-data
+      log-entry-data-to-storage-topic: log-entry-data-to-storage-topic
+    redis:
+      redis-host: 127.0.0.1
+      redis-port: 6379
+      metrics-data-queue-name-for-service-discovery: service_discovery
+      metrics-data-queue-name-to-persistent-storage: metrics:to_persistent_storage
+      metrics-data-queue-name-to-alerter: metrics:to_alerter
+      metrics-data-queue-name-to-real-time-storage: metrics:to_realtime_storage
+      alerts-data-queue-name: alerts
+      log-entry-queue-name: log:to_alerter
+      log-entry-to-storage-queue-name: log:to_storage
 
 warehouse:
   store:
@@ -143,10 +176,28 @@ warehouse:
       # (please set this configuration reasonably as history records can affect performance when it is large)
       max-history-record-num: 6000
     victoria-metrics:
+      # Standalone mode toggle — must be set to false when using cluster mode
       enabled: false
       url: http://localhost:8428
       username: root
       password: root
+      insert:
+        buffer-size: 100
+        flush-interval: 3
+        compression:
+          enabled: false
+      cluster:
+        enabled: false
+        select:
+          url: http://localhost:8481
+          username: root
+          password: root
+        insert:
+          url: http://localhost:8480
+          username: root
+          password: root
+          buffer-size: 1000
+          flush-interval: 3
     td-engine:
       enabled: false
       driver-class-name: com.taosdata.jdbc.rs.RestfulDriver
@@ -161,6 +212,11 @@ warehouse:
       database: public
       username: greptime
       password: greptime
+    questdb:
+      enabled: false
+      url: localhost:9000
+      username: admin
+      password: quest
     iot-db:
       enabled: false
       host: 127.0.0.1
@@ -244,10 +300,16 @@ alerter:
       region: AWS_REGION_FOR_END_USER_MESSAGING
     twilio:
       account-sid: YOUR_ACCOUNT_SID
-      auth-token: YOUR_AUTH_TOKEN 
+      auth-token: YOUR_AUTH_TOKEN
       twilio-phone-number: YOUR_TWILIO_PHONE_NUMBER
 scheduler:
   server:
     enabled: true
     port: 1158
-    
+
+grafana:
+  enabled: false
+  url: http://127.0.0.1:3000
+  expose-url: http://127.0.0.1:3000
+  username: admin
+  password: admin
diff --git a/script/assembly/server/assembly-docker.xml b/script/assembly/server/assembly-docker.xml
index e7f94355ed..14d5dbccb8 100644
--- a/script/assembly/server/assembly-docker.xml
+++ b/script/assembly/server/assembly-docker.xml
@@ -60,7 +60,7 @@ http://maven.apache.org/ASSEMBLY/2.0.0 ">
 
         <!-- Configuration files under the src/main/resources/define directory are packaged to the define directory -->
         <fileSet>
-            <directory>src/main/resources</directory>
+            <directory>../hertzbeat-manager/src/main/resources</directory>
             <includes>
                 <include>define/**</include>
             </includes>
diff --git a/script/assembly/server/assembly-linux-amd64.xml b/script/assembly/server/assembly-linux-amd64.xml
index 0fbcc74446..be317b21f2 100644
--- a/script/assembly/server/assembly-linux-amd64.xml
+++ b/script/assembly/server/assembly-linux-amd64.xml
@@ -61,7 +61,7 @@ http://maven.apache.org/ASSEMBLY/2.0.0 ">
 
         <!-- Configuration files under the src/main/resources/define directory are packaged to the define directory -->
         <fileSet>
-            <directory>src/main/resources</directory>
+            <directory>../hertzbeat-manager/src/main/resources</directory>
             <includes>
                 <include>define/**</include>
             </includes>
diff --git a/script/assembly/server/assembly-linux-arm64.xml b/script/assembly/server/assembly-linux-arm64.xml
index a608ff4de7..8d6801e3d6 100644
--- a/script/assembly/server/assembly-linux-arm64.xml
+++ b/script/assembly/server/assembly-linux-arm64.xml
@@ -61,7 +61,7 @@ http://maven.apache.org/ASSEMBLY/2.0.0 ">
 
         <!-- Configuration files under the src/main/resources/define directory are packaged to the define directory -->
         <fileSet>
-            <directory>src/main/resources</directory>
+            <directory>../hertzbeat-manager/src/main/resources</directory>
             <includes>
                 <include>define/**</include>
             </includes>
diff --git a/script/assembly/server/assembly-macos-amd64.xml b/script/assembly/server/assembly-macos-amd64.xml
index 5587fc8e59..152b67b198 100644
--- a/script/assembly/server/assembly-macos-amd64.xml
+++ b/script/assembly/server/assembly-macos-amd64.xml
@@ -61,7 +61,7 @@ http://maven.apache.org/ASSEMBLY/2.0.0 ">
 
         <!-- Configuration files under the src/main/resources/define directory are packaged to the define directory -->
         <fileSet>
-            <directory>src/main/resources</directory>
+            <directory>../hertzbeat-manager/src/main/resources</directory>
             <includes>
                 <include>define/**</include>
             </includes>
diff --git a/script/assembly/server/assembly-macos-arm64.xml b/script/assembly/server/assembly-macos-arm64.xml
index 9f5fb10048..385bfebb9b 100644
--- a/script/assembly/server/assembly-macos-arm64.xml
+++ b/script/assembly/server/assembly-macos-arm64.xml
@@ -60,7 +60,7 @@ http://maven.apache.org/ASSEMBLY/2.0.0 ">
 
         <!-- Configuration files under the src/main/resources/define directory are packaged to the define directory -->
         <fileSet>
-            <directory>src/main/resources</directory>
+            <directory>../hertzbeat-manager/src/main/resources</directory>
             <includes>
                 <include>define/**</include>
             </includes>
diff --git a/script/assembly/server/assembly-windows-64.xml b/script/assembly/server/assembly-windows-64.xml
index ccf521c633..94a42b2eb1 100644
--- a/script/assembly/server/assembly-windows-64.xml
+++ b/script/assembly/server/assembly-windows-64.xml
@@ -61,7 +61,7 @@ http://maven.apache.org/ASSEMBLY/2.0.0 ">
 
         <!-- Configuration files under the src/main/resources/define directory are packaged to the define directory -->
         <fileSet>
-            <directory>src/main/resources</directory>
+            <directory>../hertzbeat-manager/src/main/resources</directory>
             <includes>
                 <include>define/**</include>
             </includes>
diff --git a/script/assembly/server/assembly.xml b/script/assembly/server/assembly.xml
index cdec82d8e2..60aad0f744 100644
--- a/script/assembly/server/assembly.xml
+++ b/script/assembly/server/assembly.xml
@@ -60,7 +60,7 @@ http://maven.apache.org/ASSEMBLY/2.0.0 ">
 
         <!-- Configuration files under the src/main/resources/define directory are packaged to the define directory -->
         <fileSet>
-            <directory>src/main/resources</directory>
+            <directory>../hertzbeat-manager/src/main/resources</directory>
             <includes>
                 <include>define/**</include>
             </includes>
diff --git a/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml b/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml
index d98df3fe9a..1e847ec970 100644
--- a/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml
+++ b/script/docker-compose/hertzbeat-mysql-iotdb/conf/application.yml
@@ -240,10 +240,3 @@ grafana:
   url: http://127.0.0.1:3000
   username: admin
   password: admin
-
-ai:
-  type:
-  model:
-  api-key:
-  api-secret:
-  api-url:
diff --git a/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml b/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml
index b2f0e77afb..8f55b03994 100644
--- a/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml
+++ b/script/docker-compose/hertzbeat-mysql-tdengine/conf/application.yml
@@ -238,10 +238,3 @@ grafana:
   username: admin
   password: admin
 
-ai:
-  type:
-  model:
-  api-key:
-  api-secret:
-  api-url:
-
diff --git a/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/application.yml b/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/application.yml
index c48aa31d80..b85eadbce1 100644
--- a/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/application.yml
+++ b/script/docker-compose/hertzbeat-mysql-victoria-metrics/conf/application.yml
@@ -240,10 +240,3 @@ grafana:
   url: http://127.0.0.1:3000
   username: admin
   password: admin
-
-ai:
-  type:
-  model:
-  api-key:
-  api-secret:
-  api-url:
diff --git a/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/application.yml b/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/application.yml
index 15f3660b52..6d3ad23061 100644
--- a/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/application.yml
+++ b/script/docker-compose/hertzbeat-postgresql-victoria-metrics/conf/application.yml
@@ -239,10 +239,3 @@ grafana:
   url: http://127.0.0.1:3000
   username: admin
   password: admin
-
-ai:
-  type:
-  model:
-  api-key:
-  api-secret:
-  api-url:
diff --git a/web-app/src/app/layout/basic/basic.component.less b/web-app/src/app/layout/basic/basic.component.less
index 9407b354bc..7803a9ef5b 100644
--- a/web-app/src/app/layout/basic/basic.component.less
+++ b/web-app/src/app/layout/basic/basic.component.less
@@ -107,7 +107,7 @@
     grid-area: header !important;
     background: linear-gradient(135deg, var(--primary-color, @primary-color) 0%, var(--primary-color-light, lighten(@primary-color, 10%)) 100%) !important;
     box-shadow: 0 4px 20px var(--shadow-color, rgba(0, 0, 0, 0.08)) !important;
-    border-radius: 16px !important;
+    border-radius: 12px !important;
     backdrop-filter: blur(10px) !important;
     transition: all 0.3s ease !important;
     position: relative !important;
@@ -147,7 +147,7 @@
   .alain-default__aside {
     grid-area: sidebar !important;
     background: var(--sidebar-background, #ffffff) !important;
-    border-radius: 16px !important;
+    border-radius: 12px !important;
     box-shadow: 0 8px 32px var(--shadow-color, rgba(0, 0, 0, 0.06)) !important;
     border: 1px solid var(--border-color, rgba(255, 255, 255, 0.2)) !important;
     backdrop-filter: blur(20px) !important;
@@ -167,7 +167,7 @@
   .alain-default__content {
     grid-area: content !important;
     background: var(--content-background, #ffffff) !important;
-    border-radius: 16px !important;
+    border-radius: 12px !important;
     box-shadow: 0 8px 32px var(--shadow-color, rgba(0, 0, 0, 0.06)) !important;
     border: 1px solid var(--border-color, rgba(255, 255, 255, 0.2)) !important;
     backdrop-filter: blur(20px) !important;
@@ -183,7 +183,7 @@
   /* Sidebar navigation modern styling */
   .sidebar-nav__item {
     margin: 4px 12px;
-    border-radius: 12px;
+    border-radius: 8px;
     border-left: none;
     transition: all 0.3s ease;
     overflow: hidden;
@@ -197,7 +197,7 @@
   .sidebar-nav__selected {
     background: linear-gradient(135deg, rgba(63, 81, 181, 0.12) 0%, rgba(63, 81, 181, 0.08) 100%);
     border-left: none;
-    border-radius: 12px;
+    border-radius: 8px;
     position: relative;
   }
 
@@ -215,7 +215,7 @@
 
   .sidebar-nav__item-link {
     padding: 12px 16px;
-    border-radius: 8px;
+    border-radius: 6px;
     transition: all 0.3s ease;
     font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
     font-weight: 500;
@@ -227,7 +227,7 @@
 
   /* Header items modern styling */
   .alain-default__nav-item {
-    border-radius: 8px;
+    border-radius: 6px;
     margin: 0 4px;
     transition: all 0.3s ease;
   }
@@ -246,7 +246,7 @@
   /* Search component modern styling */
   .alain-default__search {
     .ant-input-affix-wrapper {
-      border-radius: 20px;
+      border-radius: 16px;
       background: rgba(255, 255, 255, 0.15);
       border: 1px solid rgba(255, 255, 255, 0.2);
       backdrop-filter: blur(10px);
@@ -264,7 +264,7 @@
 
   /* Logo area styling */
   .alain-default__header-logo {
-    border-radius: 12px;
+    border-radius: 8px;
     margin: 8px;
     transition: all 0.3s ease;
   }
@@ -280,18 +280,18 @@
     }
 
     .alain-default__header {
-      border-radius: 12px;
+      border-radius: 8px;
     }
 
     .alain-default__aside {
       margin-top: 4px;
-      border-radius: 12px;
+      border-radius: 8px;
     }
 
     .alain-default__content {
       margin-top: 4px;
       margin-left: 4px;
-      border-radius: 12px;
+      border-radius: 8px;
     }
   }
 
@@ -363,23 +363,23 @@ global-footer {
 /* AI Chat Modal Styles */
 :host ::ng-deep .ai-chat-modal {
   .ant-modal {
-    border-radius: 16px !important;
+    border-radius: 12px !important;
     overflow: hidden !important;
   }
   .ant-modal-content {
-    border-radius: 16px !important;
+    border-radius: 12px !important;
     overflow: hidden !important;
   }
 
 
 
   .ant-modal-header {
-    border-radius: 16px 16px 0 0 !important;
+    border-radius: 12px 12px 0 0 !important;
     margin: 0 !important;
     padding: 16px !important;
   }
   .ant-modal-body {
-    border-radius: 0 0 16px 16px !important;
+    border-radius: 0 0 12px 12px !important;
     padding: 0 !important;
   }
 
diff --git a/web-app/src/app/layout/basic/basic.component.ts b/web-app/src/app/layout/basic/basic.component.ts
index 38d7ad3c54..1c92a136f4 100644
--- a/web-app/src/app/layout/basic/basic.component.ts
+++ b/web-app/src/app/layout/basic/basic.component.ts
@@ -18,13 +18,8 @@ import { AiChatModalService } from '../../shared/services/ai-chat-modal.service'
         </a>
       </layout-default-header-item>
 
-      <layout-default-header-item direction="left" hidden="pc">
-        <div layout-default-header-item-trigger (click)="searchToggleStatus = !searchToggleStatus">
-          <i nz-icon nzType="search"></i>
-        </div>
-      </layout-default-header-item>
       <layout-default-header-item direction="middle">
-        <header-search class="alain-default__search" [toggleChange]="searchToggleStatus"></header-search>
+        <header-ai-chat class="alain-default__ai-chat"></header-ai-chat>
       </layout-default-header-item>
       <layout-default-header-item direction="right" hidden="mobile">
         <header-notify></header-notify>
@@ -101,6 +96,7 @@ export class LayoutBasicComponent implements OnDestroy {
   };
   avatar: string = `./assets/img/avatar.svg`;
   searchToggleStatus = false;
+  aiChatToggleStatus = false;
   showSettingDrawer = !environment.production;
   version = CONSTANTS.VERSION;
   currentYear = new Date().getFullYear();
diff --git a/web-app/src/app/layout/basic/widgets/chat-input.component.ts b/web-app/src/app/layout/basic/widgets/chat-input.component.ts
new file mode 100644
index 0000000000..6a635c1ef5
--- /dev/null
+++ b/web-app/src/app/layout/basic/widgets/chat-input.component.ts
@@ -0,0 +1,89 @@
+import { Component, Input, Output, EventEmitter, Inject } from '@angular/core';
+import { I18NService } from '@core';
+import { ALAIN_I18N_TOKEN } from '@delon/theme';
+
+import { AiChatModalService } from '../../../shared/services/ai-chat-modal.service';
+
+@Component({
+  selector: 'header-ai-chat',
+  template: `
+    <div class="ai-chat-input-container">
+      <nz-input-group [nzSuffix]="iconTpl" nzCompact class="ai-chat-input-group">
+        <ng-template #iconTpl>
+          <i nz-icon [hidden]="inputMessage.trim()" [nzType]="'message'"></i>
+          <i nz-icon (click)="onSubmit()" [hidden]="!inputMessage.trim()" [nzType]="'send'"></i>
+        </ng-template>
+        <input
+          nz-input
+          type="text"
+          class="ai-chat-input"
+          [(ngModel)]="inputMessage"
+          [placeholder]="'ai.chat.input.placeholder' | i18n"
+          (keydown.enter)="onSubmit()"
+          (focus)="onFocus()"
+          (blur)="onBlur()"
+        />
+      </nz-input-group>
+    </div>
+  `,
+  styles: [
+    `
+      .ai-chat-input-container {
+        display: flex;
+        align-items: center;
+        width: 100%;
+        max-width: 500px;
+      }
+
+      .ai-chat-input-group {
+        width: 100%;
+        display: flex;
+      }
+
+      .ai-chat-input {
+        flex: 1;
+        min-width: 300px;
+        border-radius: 8px;
+        border-right: none !important;
+      }
+
+      .ai-chat-input:focus {
+        box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
+        border-color: #1890ff;
+      }
+
+      [data-theme='dark'] .ai-chat-input {
+        background-color: #141414;
+        border-color: #434343;
+        color: #fff;
+      }
+
+      [data-theme='dark'] .ai-chat-input::placeholder {
+        color: #8c8c8c;
+      }
+    `
+  ]
+})
+export class HeaderAiChatComponent {
+  @Input() disabled = false;
+  @Output() readonly search = new EventEmitter<string>();
+
+  inputMessage = '';
+
+  constructor(private aiChatModalService: AiChatModalService, @Inject(ALAIN_I18N_TOKEN) private i18n: I18NService) {}
+
+  onSubmit(): void {
+    if (this.inputMessage.trim()) {
+      this.aiChatModalService.openChatModal(this.inputMessage.trim());
+      this.inputMessage = '';
+    }
+  }
+
+  onFocus(): void {
+    // 可以添加聚焦时的逻辑
+  }
+
+  onBlur(): void {
+    // 可以添加失焦时的逻辑
+  }
+}
diff --git a/web-app/src/app/layout/basic/widgets/search.component.less b/web-app/src/app/layout/basic/widgets/search.component.less
deleted file mode 100644
index 58e3e3ab5b..0000000000
--- a/web-app/src/app/layout/basic/widgets/search.component.less
+++ /dev/null
@@ -1,74 +0,0 @@
-.search-input-group {
-  margin: 10px 0;
-  border-radius: 16px !important;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
-}
-
-.search-autocomplete {
-  max-height: 300px;
-  overflow-y: auto;
-  border-radius: 8px;
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
-  background-color: #ffffff;
-}
-
-.search-option {
-  padding: 12px;
-  transition: background-color 0.3s;
-  border-bottom: 1px solid #f0f0f0;
-
-  &:hover {
-    background-color: #f5f5f5;
-  }
-}
-
-.search-host {
-  display: block;
-  font-size: 14px;
-}
-
-.search-arrow {
-  float: right;
-}
-
-.monitor-info {
-  display: flex;
-  flex-direction: column;
-  align-items: flex-start;
-  justify-content: flex-start;
-}
-
-.monitor-name {
-  font-size: 14px;
-  margin-bottom: 2px;
-}
-
-.monitor-host {
-  color: #888;
-  font-size: 12px;
-  margin-bottom: 5px;
-  margin-left: 8px;
-}
-
-.monitor-labels {
-  display: flex;
-  flex-direction: row;
-  flex-wrap: wrap;
-  margin-top: 0;
-}
-
-.monitor-label {
-  display: inline-block;
-  background-color: #e0f7fa;
-  color: #00796b;
-  border-radius: 4px;
-  padding: 6px 10px;
-  margin: 5px;
-  font-size: 12px;
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-  transition: background-color 0.3s;
-
-  &:hover {
-    background-color: #b2ebf2;
-  }
-}
diff --git a/web-app/src/app/layout/basic/widgets/search.component.ts b/web-app/src/app/layout/basic/widgets/search.component.ts
deleted file mode 100644
index e4f40ccd5a..0000000000
--- a/web-app/src/app/layout/basic/widgets/search.component.ts
+++ /dev/null
@@ -1,181 +0,0 @@
-import {
-  AfterViewInit,
-  ChangeDetectionStrategy,
-  ChangeDetectorRef,
-  Component,
-  ElementRef,
-  EventEmitter,
-  HostBinding,
-  Input,
-  OnDestroy,
-  Output
-} from '@angular/core';
-import { Router, NavigationEnd } from '@angular/router';
-import { BehaviorSubject } from 'rxjs';
-import { debounceTime, distinctUntilChanged, tap, filter } from 'rxjs/operators';
-
-import { Monitor } from '../../../pojo/Monitor';
-import { MonitorService } from '../../../service/monitor.service';
-
-@Component({
-  selector: 'header-search',
-  template: `
-    <nz-input-group [nzPrefix]="iconTpl" [nzSuffix]="loadingTpl" class="search-input-group">
-      <ng-template #iconTpl>
-        <i nz-icon [nzType]="focus ? 'arrow-down' : 'search'"></i>
-      </ng-template>
-      <ng-template #loadingTpl>
-        <i *ngIf="loading" nz-icon nzType="loading"></i>
-      </ng-template>
-      <input
-        type="text"
-        nz-input
-        [(ngModel)]="q"
-        [nzAutocomplete]="auto"
-        (input)="search($event)"
-        (focus)="qFocus()"
-        (blur)="qBlur()"
-        [attr.placeholder]="'menu.search.placeholder' | i18n"
-        class="search-input"
-      />
-    </nz-input-group>
-    <nz-autocomplete nzBackfill="false" nzDefaultActiveFirstOption #auto class="search-autocomplete">
-      <nz-auto-option
-        *ngFor="let option of options"
-        [nzValue]="option.id"
-        [nzLabel]="option.name"
-        (click)="onOptionSelect(option)"
-        class="search-option"
-      >
-        <a>
-          <div class="monitor-info">
-            <div>
-              <span class="monitor-name">{{ option.name }}</span>
-              <span class="monitor-host">{{ option.host }}</span>
-            </div>
-            <div class="monitor-labels">
-              <span *ngFor="let label of option.labels | keyvalue" class="monitor-label">{{ label.key + ' : ' + label.value }}</span>
-            </div>
-          </div>
-        </a>
-      </nz-auto-option>
-    </nz-autocomplete>
-  `,
-  changeDetection: ChangeDetectionStrategy.OnPush,
-  styleUrls: ['./search.component.less']
-})
-export class HeaderSearchComponent implements AfterViewInit, OnDestroy {
-  q = '';
-  qIpt: HTMLInputElement | null = null;
-  options: Monitor[] = [];
-  search$ = new BehaviorSubject('');
-  loading = false;
-
-  @HostBinding('class.alain-default__search-focus')
-  focus = false;
-  @HostBinding('class.alain-default__search-toggled')
-  searchToggled = false;
-
-  @Input()
-  set toggleChange(value: boolean) {
-    if (typeof value === 'undefined') {
-      return;
-    }
-    this.searchToggled = value;
-    this.focus = value;
-    if (value) {
-      setTimeout(() => this.qIpt!.focus());
-    }
-  }
-  @Output() readonly toggleChangeChange = new EventEmitter<boolean>();
-
-  constructor(
-    private router: Router,
-    private el: ElementRef<HTMLElement>,
-    private cdr: ChangeDetectorRef,
-    private monitorSvc: MonitorService
-  ) {
-    this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
-      this.resetSearch();
-    });
-  }
-
-  ngAfterViewInit(): void {
-    this.qIpt = this.el.nativeElement.querySelector('.ant-input') as HTMLInputElement;
-    this.initOptions();
-  }
-
-  initOptions() {
-    this.search$
-      .pipe(
-        debounceTime(500),
-        distinctUntilChanged(),
-        tap({
-          complete: () => {
-            this.loading = true;
-          }
-        })
-      )
-      .subscribe(value => {
-        // Remote loading of search data
-        let searchMonitors$ = this.monitorSvc.searchMonitors(undefined, undefined, value, 9, 0, 10).subscribe(
-          message => {
-            this.loading = false;
-            searchMonitors$.unsubscribe();
-            if (message.code === 0) {
-              let page = message.data;
-              if (page.content != undefined) {
-                this.options = page.content;
-              } else {
-                this.options = [];
-              }
-              this.cdr.detectChanges();
-            } else {
-              console.warn(message.msg);
-            }
-          },
-          error => {
-            this.loading = false;
-            searchMonitors$.unsubscribe();
-            console.error(error.msg);
-          }
-        );
-      });
-  }
-
-  qFocus(): void {
-    this.focus = true;
-  }
-
-  qBlur(): void {
-    this.focus = false;
-    this.searchToggled = false;
-    this.options = [];
-    this.toggleChangeChange.emit(false);
-  }
-
-  search(ev: Event): void {
-    this.search$.next((ev.target as HTMLInputElement).value);
-  }
-
-  onOptionSelect(option: any) {
-    this.router.navigate([`/monitors/${option.id}`]);
-    this.resetSearch();
-    if (this.qIpt) {
-      this.qIpt.blur();
-    }
-    this.qBlur();
-  }
-
-  resetSearch() {
-    if (this.qIpt) {
-      this.qIpt!.value = '';
-    }
-    this.initOptions();
-  }
-
-  ngOnDestroy(): void {
-    this.search$.complete();
-    this.search$.unsubscribe();
-  }
-}
diff --git a/web-app/src/app/layout/layout.module.ts b/web-app/src/app/layout/layout.module.ts
index 5b3f154b54..f10d631068 100644
--- a/web-app/src/app/layout/layout.module.ts
+++ b/web-app/src/app/layout/layout.module.ts
@@ -21,7 +21,7 @@ import { NzSpinModule } from 'ng-zorro-antd/spin';
 import { LayoutBasicComponent } from './basic/basic.component';
 import { HeaderFullScreenComponent } from './basic/widgets/fullscreen.component';
 import { HeaderI18nComponent } from './basic/widgets/i18n.component';
-import { HeaderSearchComponent } from './basic/widgets/search.component';
+import { HeaderAiChatComponent } from './basic/widgets/chat-input.component';
 import { HeaderUserComponent } from './basic/widgets/user.component';
 import { HeaderNotifyComponent } from './basic/widgets/notify.component';
 import { LayoutBlankComponent } from './blank/blank.component';
@@ -29,7 +29,7 @@ import { LayoutBlankComponent } from './blank/blank.component';
 const COMPONENTS = [LayoutBasicComponent, LayoutBlankComponent, HeaderI18nComponent];
 
 const HEADER_COMPONENTS = [
-  HeaderSearchComponent,
+  HeaderAiChatComponent,
   HeaderFullScreenComponent,
   HeaderI18nComponent,
   HeaderUserComponent,
diff --git a/web-app/src/app/pojo/ModelProviderConfig.ts b/web-app/src/app/pojo/ModelProviderConfig.ts
index 5fe6dbbe31..7a3d155257 100644
--- a/web-app/src/app/pojo/ModelProviderConfig.ts
+++ b/web-app/src/app/pojo/ModelProviderConfig.ts
@@ -18,8 +18,6 @@
  */
 
 export class ModelProviderConfig {
-  enable: boolean = false;
-  status: boolean = true;
   error!: string;
   type!: string;
   code: string = 'openai';
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.html b/web-app/src/app/routes/dashboard/dashboard.component.html
index 8717762ea4..deca2ba1f9 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.html
+++ b/web-app/src/app/routes/dashboard/dashboard.component.html
@@ -347,7 +347,7 @@
   <div nz-row nzGutter="16" style="margin-top: 20px; height: 500px">
     <div nz-col [nzXs]="{ span: 24 }" [nzSm]="{ span: 24 }" [nzMd]="{ span: 6 }" style="height: 100%">
       <nz-spin [nzSpinning]="wordCloudDataLoading">
-        <nz-card class="dashboard-chart-card" style="border-radius: 16px !important; height: 100%; width: 100%">
+        <nz-card class="dashboard-chart-card" style="border-radius: 12px !important; height: 100%; width: 100%">
           <angular-tag-cloud
             class="br-4"
             *ngIf="!wordCloudDataLoading"
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.less b/web-app/src/app/routes/dashboard/dashboard.component.less
index 4f13f59780..8bde1cb456 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.less
+++ b/web-app/src/app/routes/dashboard/dashboard.component.less
@@ -151,7 +151,7 @@
 
 .hoverCard {
   &:hover {
-    transform: scale(104%);
+    transform: scale(101%);
     transition: 0.2s;
   }
 }
diff --git a/web-app/src/app/routes/dashboard/dashboard.component.ts b/web-app/src/app/routes/dashboard/dashboard.component.ts
index e73c58e9a4..4df99747e5 100644
--- a/web-app/src/app/routes/dashboard/dashboard.component.ts
+++ b/web-app/src/app/routes/dashboard/dashboard.component.ts
@@ -135,11 +135,11 @@ export class DashboardComponent implements OnInit, OnDestroy {
 
   slideConfig = {
     infinite: true,
-    speed: 1200,
+    speed: 1800,
     slidesToShow: 4,
     slidesToScroll: 1,
     autoplay: true,
-    autoplaySpeed: 1200,
+    autoplaySpeed: 2400,
     rows: 1,
     responsive: [
       {
diff --git a/web-app/src/app/service/ai-chat.service.ts b/web-app/src/app/service/ai-chat.service.ts
index 7db164befe..37f308af8a 100644
--- a/web-app/src/app/service/ai-chat.service.ts
+++ b/web-app/src/app/service/ai-chat.service.ts
@@ -27,19 +27,20 @@ import { LocalStorageService } from './local-storage.service';
 export interface ChatMessage {
   content: string;
   role: 'user' | 'assistant';
-  timestamp: Date;
+  gmtCreate: Date;
 }
 
-export interface ConversationDto {
-  conversationId: string;
-  createdAt: Date;
-  updatedAt: Date;
+export interface ChatConversation {
+  id: number;
+  title: string;
+  gmtCreated: Date;
+  gmtUpdate: Date;
   messages: ChatMessage[];
 }
 
 export interface ChatRequestContext {
   message: string;
-  conversationId?: string;
+  conversationId?: number;
 }
 
 const chat_uri = '/chat';
@@ -53,35 +54,35 @@ export class AiChatService {
   /**
    * Create a new conversation
    */
-  createConversation(): Observable<Message<ConversationDto>> {
-    return this.http.post<Message<ConversationDto>>(`${chat_uri}/conversations`, {});
+  createConversation(): Observable<Message<ChatConversation>> {
+    return this.http.post<Message<ChatConversation>>(`${chat_uri}/conversations`, {});
   }
 
   /**
    * Get all conversations
    */
-  getConversations(): Observable<Message<ConversationDto[]>> {
-    return this.http.get<Message<ConversationDto[]>>(`${chat_uri}/conversations`);
+  getConversations(): Observable<Message<ChatConversation[]>> {
+    return this.http.get<Message<ChatConversation[]>>(`${chat_uri}/conversations`);
   }
 
   /**
    * Get a specific conversation with its history
    */
-  getConversation(conversationId: string): Observable<Message<ConversationDto>> {
-    return this.http.get<Message<ConversationDto>>(`${chat_uri}/conversations/${conversationId}`);
+  getConversation(conversationId: number): Observable<Message<ChatConversation>> {
+    return this.http.get<Message<ChatConversation>>(`${chat_uri}/conversations/${conversationId}`);
   }
 
   /**
    * Delete a conversation
    */
-  deleteConversation(conversationId: string): Observable<Message<void>> {
+  deleteConversation(conversationId: number): Observable<Message<void>> {
     return this.http.delete<Message<void>>(`${chat_uri}/conversations/${conversationId}`);
   }
 
   /**
    * Send a message and get streaming response
    */
-  streamChat(message: string, conversationId?: string): Observable<ChatMessage> {
+  streamChat(message: string, conversationId?: number): Observable<ChatMessage> {
     const responseSubject = new Subject<ChatMessage>();
 
     const requestBody: ChatRequestContext = { message };
@@ -147,7 +148,7 @@ export class AiChatService {
                       responseSubject.next({
                         content: data.response || '',
                         role: 'assistant',
-                        timestamp: data.timestamp ? new Date(data.timestamp) : new Date()
+                        gmtCreate: data.timestamp ? new Date(data.timestamp) : new Date()
                       });
                     }
                   } catch (parseError) {
@@ -156,7 +157,7 @@ export class AiChatService {
                       responseSubject.next({
                         content: jsonStr,
                         role: 'assistant',
-                        timestamp: new Date()
+                        gmtCreate: new Date()
                       });
                     }
                   }
diff --git a/web-app/src/app/shared/components/ai-chat/ai-chat.module.ts b/web-app/src/app/shared/components/ai-chat/ai-chat.module.ts
index ca16c108b2..a154954c7a 100644
--- a/web-app/src/app/shared/components/ai-chat/ai-chat.module.ts
+++ b/web-app/src/app/shared/components/ai-chat/ai-chat.module.ts
@@ -30,7 +30,8 @@ import { NzMessageModule } from 'ng-zorro-antd/message';
 import { NzModalModule } from 'ng-zorro-antd/modal';
 import { NzSelectModule } from 'ng-zorro-antd/select';
 import { NzSpinModule } from 'ng-zorro-antd/spin';
-import { MarkdownPipe } from 'ngx-markdown';
+import { NzTooltipDirective } from 'ng-zorro-antd/tooltip';
+import { MarkdownComponent } from 'ngx-markdown';
 
 import { ChatComponent } from './chat.component';
 
@@ -50,7 +51,8 @@ import { ChatComponent } from './chat.component';
     NzModalModule,
     NzSelectModule,
     NzSpinModule,
-    MarkdownPipe
+    MarkdownComponent,
+    NzTooltipDirective
   ],
   exports: [ChatComponent]
 })
diff --git a/web-app/src/app/shared/components/ai-chat/chat.component.html b/web-app/src/app/shared/components/ai-chat/chat.component.html
index a44748bb73..a09c0a91c1 100644
--- a/web-app/src/app/shared/components/ai-chat/chat.component.html
+++ b/web-app/src/app/shared/components/ai-chat/chat.component.html
@@ -22,9 +22,9 @@
   <div class="chat-sidebar" [class.collapsed]="sidebarCollapsed">
     <div class="sidebar-header">
       <h3>{{ 'menu.extras.ai.chat' | i18n }}</h3>
-      <button nz-button nzType="primary" nzSize="small" (click)="createNewConversation()" [nzLoading]="isLoading">
+      <button nz-button nzType="primary" nzSize="small" (click)="createNewConversation()" [disabled]="isSendingMessage">
         <i nz-icon nzType="plus"></i>
-        New Chat
+        {{ 'ai.chat.new-chat' | i18n }}
       </button>
     </div>
 
@@ -32,7 +32,7 @@
       <div
         *ngFor="let conversation of conversations"
         class="conversation-item"
-        [class.active]="currentConversation?.conversationId === conversation.conversationId"
+        [class.active]="currentConversation?.id === conversation.id"
         (click)="selectConversation(conversation)"
       >
         <div class="conversation-content">
@@ -40,7 +40,7 @@
             {{ getConversationTitle(conversation) }}
           </div>
           <div class="conversation-time">
-            {{ conversation.updatedAt | date : 'MMM d, HH:mm' }}
+            {{ conversation.gmtUpdate | date : 'MMM d, HH:mm' }}
           </div>
         </div>
         <button nz-button nzType="text" nzSize="small" nzDanger (click)="deleteConversation(conversation, $event)" class="delete-btn">
@@ -62,40 +62,38 @@
         <h2 *ngIf="currentConversation">
           {{ getConversationTitle(currentConversation) }}
         </h2>
-        <h2 *ngIf="!currentConversation"> HertzBeat AI Agent </h2>
+        <h2 *ngIf="!currentConversation">{{ 'ai.chat.title' | i18n }}</h2>
       </div>
     </div>
 
     <!-- Messages area -->
     <div class="messages-container" #messagesContainer>
       <!-- Loading indicator -->
-      <div *ngIf="isLoading" class="loading-container">
+      <div *ngIf="isLoadingConversations" class="loading-container">
         <nz-spin nzSimple [nzSize]="'large'">
           <ng-template #indicator>
             <i nz-icon nzType="loading" nzSpin></i>
           </ng-template>
         </nz-spin>
-        <p>Loading conversation history...</p>
+        <p>{{ 'ai.chat.loading' | i18n }}</p>
       </div>
 
       <!-- Welcome message -->
-      <div *ngIf="messages.length === 0 && !isLoading" class="welcome-message">
+      <div *ngIf="messages.length === 0 && !isLoadingConversations" class="welcome-message">
         <div class="welcome-content">
           <img [src]="theme === 'dark' ? 'assets/logo_white.svg' : 'assets/logo.svg'" alt="HertzBeat Logo" class="welcome-icon" />
-          <h3>Welcome to HertzBeat AI Agent!</h3>
-          <p>
-            I'm your intelligent monitoring companion, ready to help you manage and optimize your infrastructure monitoring. You can ask me
-            to:
+          <h3 class="welcome-title">{{ 'ai.chat.welcome.title' | i18n }}</h3>
+          <p class="welcome-description">
+            {{ 'ai.chat.welcome.description' | i18n }}
           </p>
-          <ul>
-            <li>🔍 Query and manage monitors by status, type, or labels</li>
-            <li>➕ Add new monitors for websites, APIs, databases, and services</li>
-            <li>🚨 View and analyze alerts with comprehensive filtering</li>
-            <li>📊 Access real-time and historical metrics data</li>
-            <li>⚙️ Configure alert rules and thresholds</li>
-            <li>⚡ Troubleshoot performance issues across your infrastructure</li>
+          <ul class="capabilities-list">
+            <li>{{ 'ai.chat.welcome.capabilities.monitor' | i18n }}</li>
+            <li>{{ 'ai.chat.welcome.capabilities.manage' | i18n }}</li>
+            <li>{{ 'ai.chat.welcome.capabilities.metrics' | i18n }}</li>
+            <li>{{ 'ai.chat.welcome.capabilities.alerts' | i18n }}</li>
+            <li>{{ 'ai.chat.welcome.capabilities.config' | i18n }}</li>
+            <li>{{ 'ai.chat.welcome.capabilities.troubleshoot' | i18n }}</li>
           </ul>
-          <p>Ask me anything about your monitoring setup!</p>
         </div>
       </div>
 
@@ -106,16 +104,22 @@
         </div>
         <div class="message-content">
           <div class="message-header">
-            <span class="message-role">{{ message.role === 'user' ? 'You' : 'AI Assistant' }}</span>
-            <span class="message-time">{{ formatTime(message.timestamp) }}</span>
-            <span *ngIf="message.role === 'assistant' && isLoading && i === messages.length - 1" class="streaming-indicator">
-              <nz-spin nzSize="small"></nz-spin>
+            <span class="message-role">{{ message.role === 'user' ? ('ai.chat.user' | i18n) : ('ai.chat.assistant' | i18n) }}</span>
+            <span class="message-time">{{ formatTime(message.gmtCreate) }}</span>
+            <span
+              *ngIf="message.role === 'assistant' && isSendingMessage && i === messages.length - 1 && message.content !== ''"
+              class="streaming-indicator"
+            >
+              <i nz-icon nzType="loading" nzSpin style="font-size: 12px"></i>
+              <span style="font-size: 11px">Typing...</span>
             </span>
           </div>
-          <div class="message-text" [innerHTML]="message.content"></div>
-          <div *ngIf="message.role === 'assistant' && message.content === '' && isLoading" class="typing-indicator">
-            <nz-spin nzSize="small"></nz-spin>
-            <span>Starting to type...</span>
+          <div class="message-text">
+            <div *ngIf="message.role === 'user'" [innerHTML]="message.content"></div>
+            <markdown *ngIf="message.role === 'assistant'" [data]="message.content"></markdown>
+          </div>
+          <div *ngIf="message.role === 'assistant' && message.content === '' && isSendingMessage" class="typing-indicator">
+            <span>{{ 'ai.chat.typing' | i18n }}</span>
           </div>
         </div>
       </div>
@@ -129,28 +133,21 @@
             nz-input
             [(ngModel)]="newMessage"
             (keypress)="onKeyPress($event)"
-            [disabled]="isLoading"
-            placeholder="Ask me anything about monitoring..."
+            [disabled]="isSendingMessage"
+            placeholder="{{ 'ai.chat.input.placeholder' | i18n }}"
             rows="3"
             style="resize: none"
           ></textarea>
         </nz-textarea-count>
-        <button
-          nz-button
-          nzType="primary"
-          (click)="sendMessage()"
-          [disabled]="!newMessage.trim() || isLoading"
-          [nzLoading]="isLoading"
-          class="send-button"
-        >
-          <i nz-icon nzType="send"></i>
+        <button nz-button nzType="primary" (click)="sendMessage()" [disabled]="!newMessage.trim() || isSendingMessage" class="send-button">
+          <i nz-icon [nzType]="isSendingMessage ? 'loading' : 'send'" [nzSpin]="isSendingMessage"></i>
         </button>
       </div>
       <div class="input-hint">
-        <small>Press Enter to send, Shift+Enter for new line</small>
+        <small>{{ 'ai.chat.input.hint' | i18n }}</small>
         <button nz-button nzType="link" nzSize="small" (click)="onShowConfigModal()" style="float: right">
           <i nz-icon nzType="setting"></i>
-          Modify API Key
+          {{ 'ai.chat.modify-api-key' | i18n }}
         </button>
       </div>
     </div>
@@ -160,26 +157,26 @@
 <!-- OpenAI Configuration Modal -->
 <nz-modal
   [(nzVisible)]="showConfigModal"
-  nzTitle="AI Provider Configuration"
+  [nzTitle]="'ai.chat.config.title' | i18n"
   (nzOnCancel)="onCloseConfigModal()"
   (nzOnOk)="onSaveAiProviderConfig()"
   nzMaskClosable="false"
   [nzClosable]="false"
   nzWidth="700px"
   [nzOkLoading]="configLoading"
-  nzOkText="Validate & Save"
-  nzCancelText="Cancel"
+  [nzOkText]="'ai.chat.config.save' | i18n"
+  [nzCancelText]="'ai.chat.config.cancel' | i18n"
 >
   <div *nzModalContent class="-inner-content">
     <form nz-form nzLayout="vertical">
       <!-- Provider Selection -->
       <nz-form-item>
-        <nz-form-label nzRequired="true">AI Provider</nz-form-label>
-        <nz-form-control nzErrorTip="Please select an AI provider">
+        <nz-form-label nzRequired="true">{{ 'ai.chat.config.provider' | i18n }}</nz-form-label>
+        <nz-form-control [nzErrorTip]="'ai.chat.config.provider.required' | i18n">
           <nz-select
             [(ngModel)]="aiProviderConfig.code"
             name="provider"
-            nzPlaceHolder="Select AI Provider"
+            [nzPlaceHolder]="'ai.chat.config.provider.help' | i18n"
             (ngModelChange)="onProviderChange($event)"
             style="width: 100%"
           >
@@ -191,16 +188,16 @@
 
       <!-- API Key -->
       <nz-form-item>
-        <nz-form-label nzRequired="true">API Key</nz-form-label>
-        <nz-form-control nzErrorTip="API Key is required">
+        <nz-form-label nzRequired="true">{{ 'ai.chat.config.api-key' | i18n }}</nz-form-label>
+        <nz-form-control [nzErrorTip]="'ai.chat.config.api-key.required' | i18n">
           <input nz-input [(ngModel)]="aiProviderConfig.apiKey" name="apiKey" type="password" placeholder="sk-..." required />
-          <p class="form-help">Your Provider API key. The key will be validated when saved.</p>
+          <p class="form-help">{{ 'ai.chat.config.api-key.help' | i18n }}</p>
         </nz-form-control>
       </nz-form-item>
 
       <!-- Base URL -->
       <nz-form-item>
-        <nz-form-label>Base URL</nz-form-label>
+        <nz-form-label>{{ 'ai.chat.config.base-url' | i18n }}</nz-form-label>
         <nz-form-control>
           <nz-input-group [nzSuffix]="resetBtn">
             <input nz-input [(ngModel)]="aiProviderConfig.baseUrl" name="baseUrl" placeholder="https://api.openai.com/v1" />
@@ -210,23 +207,23 @@
                 nzType="link"
                 nzSize="small"
                 (click)="resetToDefaults()"
-                nzTooltipTitle="Reset to default values"
+                [nzTooltipTitle]="'ai.chat.config.reset' | i18n"
                 nz-tooltip
               >
                 <i nz-icon nzType="reload"></i>
               </button>
             </ng-template>
           </nz-input-group>
-          <p class="form-help">Custom API endpoint URL. Leave empty to use default for selected provider.</p>
+          <p class="form-help">{{ 'ai.chat.config.base-url.help' | i18n }}</p>
         </nz-form-control>
       </nz-form-item>
 
       <!-- Model -->
       <nz-form-item>
-        <nz-form-label>Model</nz-form-label>
+        <nz-form-label>{{ 'ai.chat.config.model' | i18n }}</nz-form-label>
         <nz-form-control>
           <input nz-input [(ngModel)]="aiProviderConfig.model" name="model" placeholder="gpt-4" />
-          <p class="form-help">Model name to use. Leave empty to use default for selected provider.</p>
+          <p class="form-help">{{ 'ai.chat.config.model.help' | i18n }}</p>
         </nz-form-control>
       </nz-form-item>
     </form>
diff --git a/web-app/src/app/shared/components/ai-chat/chat.component.less b/web-app/src/app/shared/components/ai-chat/chat.component.less
index 8edbb3a1c3..23a198c5d4 100644
--- a/web-app/src/app/shared/components/ai-chat/chat.component.less
+++ b/web-app/src/app/shared/components/ai-chat/chat.component.less
@@ -21,7 +21,9 @@
 
 .chat-container {
   display: flex;
-  height: 80vh; // Use viewport height for modal context
+  height: 100%;
+  min-height: 500px;
+  max-height: 80vh;
   background: @layout-body-background;
 
   .chat-sidebar {
@@ -54,6 +56,25 @@
     .conversation-list {
       flex: 1;
       overflow-y: auto;
+      scrollbar-width: thin;
+      scrollbar-color: @border-color-base transparent;
+
+      &::-webkit-scrollbar {
+        width: 6px;
+      }
+
+      &::-webkit-scrollbar-track {
+        background: transparent;
+      }
+
+      &::-webkit-scrollbar-thumb {
+        background: @border-color-base;
+        border-radius: 3px;
+      }
+
+      &::-webkit-scrollbar-thumb:hover {
+        background: @border-color-split;
+      }
 
       .conversation-item {
         padding: 12px 16px;
@@ -134,6 +155,26 @@
       padding: 16px;
       overflow-y: auto;
       background: @layout-body-background;
+      scrollbar-width: thin;
+      scrollbar-color: @border-color-base transparent;
+      scroll-behavior: smooth;
+
+      &::-webkit-scrollbar {
+        width: 6px;
+      }
+
+      &::-webkit-scrollbar-track {
+        background: transparent;
+      }
+
+      &::-webkit-scrollbar-thumb {
+        background: @border-color-base;
+        border-radius: 3px;
+      }
+
+      &::-webkit-scrollbar-thumb:hover {
+        background: @border-color-split;
+      }
 
       .loading-container {
         display: flex;
@@ -141,6 +182,7 @@
         align-items: center;
         justify-content: center;
         height: 100%;
+        opacity: 0.8;
 
         p {
           margin-top: 16px;
@@ -228,7 +270,7 @@
         .message-avatar {
           width: 32px;
           height: 32px;
-          border-radius: 16px;
+          border-radius: 8px;
           background: @background-color-light;
           display: flex;
           align-items: center;
@@ -273,61 +315,16 @@
               gap: 4px;
               color: @primary-color;
               font-size: 11px;
+              opacity: 0.8;
+
+              i {
+                font-size: 12px;
+              }
             }
           }
 
           .message-text {
-            line-height: 1.5;
-            color: @text-color;
-            white-space: pre-wrap;
             word-wrap: break-word;
-
-            // Markdown styling
-            :global {
-              p {
-                margin: 0 0 8px 0;
-
-                &:last-child {
-                  margin-bottom: 0;
-                }
-              }
-
-              code {
-                background: @background-color-light;
-                padding: 2px 4px;
-                border-radius: 3px;
-                font-family: @code-family;
-                font-size: 12px;
-                color: @text-color;
-              }
-
-              pre {
-                background: @background-color-light;
-                padding: 12px;
-                border-radius: 6px;
-                overflow-x: auto;
-                margin: 8px 0;
-                border: 1px solid @border-color-split;
-
-                code {
-                  background: none;
-                  padding: 0;
-                  color: @text-color;
-                }
-              }
-
-              ul, ol {
-                margin: 8px 0;
-                padding-left: 20px;
-              }
-
-              blockquote {
-                border-left: 4px solid @border-color-base;
-                padding-left: 12px;
-                margin: 8px 0;
-                color: @text-color-secondary;
-              }
-            }
           }
 
           .typing-indicator {
@@ -336,6 +333,9 @@
             gap: 8px;
             color: @text-color-secondary;
             font-style: italic;
+            font-size: 13px;
+            opacity: 0.7;
+            padding: 4px 0;
           }
         }
       }
@@ -395,6 +395,7 @@
       height: 100%;
       z-index: 100;
       box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
+      transition: transform 0.3s ease;
 
       &.collapsed {
         transform: translateX(-100%);
@@ -411,6 +412,46 @@
           }
         }
       }
+
+      .input-area {
+        .input-container {
+          flex-direction: column;
+          gap: 8px;
+
+          .send-button {
+            align-self: flex-end;
+            width: auto;
+            min-width: 80px;
+          }
+        }
+      }
+    }
+  }
+}
+
+// Extra small devices
+@media (max-width: 480px) {
+  .chat-container {
+    min-height: 400px;
+    max-height: 90vh;
+
+    .chat-main {
+      .messages-container {
+        padding: 12px;
+
+        .message {
+          margin-bottom: 16px;
+
+          .message-content {
+            max-width: 90%;
+            padding: 10px 12px;
+          }
+        }
+      }
+
+      .input-area {
+        padding: 12px;
+      }
     }
   }
 }
@@ -593,6 +634,47 @@ body[data-theme='dark'] .chat-container {
       color: fade(@white, 45%) !important;
     }
   }
+
+  // Fix dropdown/select styling in dark theme
+  .ant-select {
+    .ant-select-selector {
+      background: fade(@white, 8%) !important;
+      border-color: @border-color-split !important;
+      color: fade(@white, 85%) !important;
+    }
+
+    .ant-select-selection-placeholder {
+      color: fade(@white, 45%) !important;
+    }
+
+    &:hover .ant-select-selector {
+      border-color: @primary-color !important;
+    }
+
+    &.ant-select-focused .ant-select-selector {
+      border-color: @primary-color !important;
+      box-shadow: 0 0 0 2px fade(@primary-color, 20%) !important;
+    }
+  }
+
+  // Fix dropdown options styling
+  .ant-select-dropdown {
+    background: #141414 !important;
+    border: 1px solid @border-color-split !important;
+
+    .ant-select-item {
+      color: fade(@white, 85%) !important;
+
+      &:hover {
+        background: fade(@white, 8%) !important;
+      }
+
+      &.ant-select-item-option-selected {
+        background: @primary-color !important;
+        color: @white !important;
+      }
+    }
+  }
 }
 
 // Additional high-specificity overrides for dark theme
@@ -628,7 +710,7 @@ body[data-theme='dark'] .chat-container {
 
 .validation-result {
   margin-top: 8px;
-  
+
   nz-alert {
     font-size: 12px;
   }
@@ -640,29 +722,29 @@ body[data-theme='dark'] .chat-container {
     display: flex;
     align-items: center;
     gap: 8px;
-    
+
     nz-select {
       flex: 1;
     }
   }
-  
+
   .baseurl-input-row {
     display: flex;
     align-items: center;
     gap: 8px;
-    
+
     nz-input-group {
       flex: 1;
     }
-    
+
     .reset-btn {
       flex-shrink: 0;
     }
   }
-  
+
   .form-item-with-help {
     margin-bottom: 8px;
-    
+
     + .form-help {
       margin-bottom: 16px;
     }
@@ -673,11 +755,11 @@ nz-modal {
   .ant-modal-body {
     padding: 24px;
   }
-  
+
   .ant-form-item {
     margin-bottom: 16px;
   }
-  
+
   .ant-form-item-label {
     padding-bottom: 4px;
   }
diff --git a/web-app/src/app/shared/components/ai-chat/chat.component.ts b/web-app/src/app/shared/components/ai-chat/chat.component.ts
index b47365bcd6..1c3ca19434 100644
--- a/web-app/src/app/shared/components/ai-chat/chat.component.ts
+++ b/web-app/src/app/shared/components/ai-chat/chat.component.ts
@@ -17,13 +17,14 @@
  * under the License.
  */
 
-import { Component, OnInit, ViewChild, ElementRef, AfterViewChecked, ChangeDetectorRef } from '@angular/core';
+import { Component, OnInit, ViewChild, ElementRef, ChangeDetectorRef, OnDestroy, Inject } from '@angular/core';
 import { I18NService } from '@core';
+import { ALAIN_I18N_TOKEN } from '@delon/theme';
 import { NzMessageService } from 'ng-zorro-antd/message';
 import { NzModalService } from 'ng-zorro-antd/modal';
 
 import { ModelProviderConfig, PROVIDER_OPTIONS, ProviderOption } from '../../../pojo/ModelProviderConfig';
-import { AiChatService, ChatMessage, ConversationDto } from '../../../service/ai-chat.service';
+import { AiChatService, ChatMessage, ChatConversation } from '../../../service/ai-chat.service';
 import { GeneralConfigService } from '../../../service/general-config.service';
 import { ThemeService } from '../../../service/theme.service';
 
@@ -32,19 +33,22 @@ import { ThemeService } from '../../../service/theme.service';
   templateUrl: './chat.component.html',
   styleUrls: ['./chat.component.less']
 })
-export class ChatComponent implements OnInit, AfterViewChecked {
+export class ChatComponent implements OnInit, OnDestroy {
   @ViewChild('messagesContainer') private messagesContainer!: ElementRef;
 
-  conversations: ConversationDto[] = [];
-  currentConversation: ConversationDto | null = null;
+  conversations: ChatConversation[] = [];
+  currentConversation: ChatConversation | null = null;
   messages: ChatMessage[] = [];
   newMessage = '';
-  isLoading = false;
+  initialMessage = '';
+  isLoadingConversations = false;
+  isSendingMessage = false;
   sidebarCollapsed = false;
   theme: string = 'default';
+  private scrollTimeout: any;
 
-  // OpenAI Configuration
-  isOpenAiConfigured = false;
+  // Provider Configuration
+  isAiProviderConfigured = false;
   showConfigModal = false;
   configLoading = false;
   aiProviderConfig: ModelProviderConfig = new ModelProviderConfig();
@@ -54,7 +58,7 @@ export class ChatComponent implements OnInit, AfterViewChecked {
     private aiChatService: AiChatService,
     private message: NzMessageService,
     private modal: NzModalService,
-    private i18n: I18NService,
+    @Inject(ALAIN_I18N_TOKEN) private i18nSvc: I18NService,
     private cdr: ChangeDetectorRef,
     private themeSvc: ThemeService,
     private generalConfigSvc: GeneralConfigService
@@ -62,11 +66,31 @@ export class ChatComponent implements OnInit, AfterViewChecked {
 
   ngOnInit(): void {
     this.theme = this.themeSvc.getTheme() || 'default';
+    // Always load conversations first, regardless of AI configuration status
+    this.loadConversations();
     this.checkAiConfiguration();
+    if (this.initialMessage) {
+      this.newMessage = this.initialMessage;
+      setTimeout(() => this.sendMessage(), 800);
+    }
   }
 
-  ngAfterViewChecked(): void {
-    this.scrollToBottom();
+  ngOnDestroy(): void {
+    if (this.scrollTimeout) {
+      clearTimeout(this.scrollTimeout);
+    }
+  }
+
+  /**
+   * Debounced scroll to bottom to improve performance
+   */
+  private scrollToBottomDebounced(): void {
+    if (this.scrollTimeout) {
+      clearTimeout(this.scrollTimeout);
+    }
+    this.scrollTimeout = setTimeout(() => {
+      this.scrollToBottom();
+    }, 100);
   }
 
   /**
@@ -86,12 +110,14 @@ export class ChatComponent implements OnInit, AfterViewChecked {
           }
         } else {
           console.error('Error in conversations response:', response);
-          this.message.error(`Failed to load conversations: ${response.msg || 'Unknown error'}`);
+          this.message.error(`${this.i18nSvc.fanyi('ai.chat.error.conversations.load')}: ${response.msg || 'Unknown error'}`);
         }
       },
       error: error => {
         console.error('Error loading conversations:', error);
-        this.message.error(`Failed to load conversations: ${error.status} ${error.statusText || error.message}`);
+        this.message.error(
+          `${this.i18nSvc.fanyi('ai.chat.error.conversations.load')}: ${error.status} ${error.statusText || error.message}`
+        );
 
         // Create a fallback new conversation if API is not available
         console.log('Creating fallback conversation...');
@@ -110,15 +136,17 @@ export class ChatComponent implements OnInit, AfterViewChecked {
           const newConversation = response.data;
           this.conversations.unshift(newConversation);
           this.selectConversation(newConversation);
-          this.message.success('New conversation created');
+          this.message.success(this.i18nSvc.fanyi('ai.chat.conversation.created'));
         } else {
           console.error('Error in create conversation response:', response);
-          this.message.error(`Failed to create conversation: ${response.msg || 'Unknown error'}`);
+          this.message.error(`${this.i18nSvc.fanyi('ai.chat.error.conversation.create')}: ${response.msg || 'Unknown error'}`);
         }
       },
       error: error => {
         console.error('Error creating conversation:', error);
-        this.message.error(`Failed to create new conversation: ${error.status} ${error.statusText || error.message}`);
+        this.message.error(
+          `${this.i18nSvc.fanyi('ai.chat.error.conversation.create')}: ${error.status} ${error.statusText || error.message}`
+        );
 
         // Create fallback conversation
         this.createFallbackConversation();
@@ -130,36 +158,37 @@ export class ChatComponent implements OnInit, AfterViewChecked {
    * Create a fallback conversation when API is not available
    */
   createFallbackConversation(): void {
-    const fallbackConversation: ConversationDto = {
-      conversationId: `fallback-${Date.now()}`,
-      createdAt: new Date(),
-      updatedAt: new Date(),
+    const fallbackConversation: ChatConversation = {
+      id: 0,
+      title: 'Offline Conversation',
+      gmtCreated: new Date(),
+      gmtUpdate: new Date(),
       messages: []
     };
 
     this.conversations = [fallbackConversation];
     this.selectConversation(fallbackConversation);
 
-    this.message.warning('AI Chat service unavailable. Running in offline mode.');
+    this.message.warning(this.i18nSvc.fanyi('ai.chat.offline.mode'));
   }
 
   /**
    * Select a conversation and load its messages
    */
-  selectConversation(conversation: ConversationDto): void {
+  selectConversation(conversation: ChatConversation): void {
     this.currentConversation = conversation;
-    this.loadConversationHistory(conversation.conversationId);
+    this.loadConversationHistory(conversation.id);
   }
 
   /**
    * Load conversation history from the API
    */
-  loadConversationHistory(conversationId: string): void {
-    this.isLoading = true;
+  loadConversationHistory(conversationId: number): void {
+    this.isLoadingConversations = true;
 
     this.aiChatService.getConversation(conversationId).subscribe({
       next: response => {
-        this.isLoading = false;
+        this.isLoadingConversations = false;
 
         if (response.code === 0 && response.data) {
           this.messages = response.data.messages || [];
@@ -174,7 +203,7 @@ export class ChatComponent implements OnInit, AfterViewChecked {
         }
       },
       error: error => {
-        this.isLoading = false;
+        this.isLoadingConversations = false;
         console.error('Error loading conversation history:', error);
         // Fallback to the messages from the conversation list if API fails
         this.messages = this.currentConversation?.messages || [];
@@ -187,24 +216,24 @@ export class ChatComponent implements OnInit, AfterViewChecked {
   /**
    * Delete a conversation
    */
-  deleteConversation(conversation: ConversationDto, event: Event): void {
+  deleteConversation(conversation: ChatConversation, event: Event): void {
     event.stopPropagation();
 
     this.modal.confirm({
-      nzTitle: 'Delete Conversation',
-      nzContent: 'Are you sure you want to delete this conversation?',
-      nzOkText: 'Delete',
+      nzTitle: this.i18nSvc.fanyi('ai.chat.conversation.delete.title'),
+      nzContent: this.i18nSvc.fanyi('ai.chat.conversation.delete.content'),
+      nzOkText: this.i18nSvc.fanyi('ai.chat.conversation.delete.confirm'),
       nzOkType: 'primary',
       nzOkDanger: true,
       nzOnOk: () => {
-        this.aiChatService.deleteConversation(conversation.conversationId).subscribe({
+        this.aiChatService.deleteConversation(conversation.id).subscribe({
           next: response => {
             if (response.code === 0) {
               // Remove from conversations list
-              this.conversations = this.conversations.filter(c => c.conversationId !== conversation.conversationId);
+              this.conversations = this.conversations.filter(c => c.id !== conversation.id);
 
               // If this was the current conversation, select another or create new
-              if (this.currentConversation?.conversationId === conversation.conversationId) {
+              if (this.currentConversation?.id === conversation.id) {
                 if (this.conversations.length > 0) {
                   this.selectConversation(this.conversations[0]);
                 } else {
@@ -212,12 +241,12 @@ export class ChatComponent implements OnInit, AfterViewChecked {
                 }
               }
 
-              this.message.success('Conversation deleted');
+              this.message.success(this.i18nSvc.fanyi('ai.chat.conversation.delete.success'));
             }
           },
           error: error => {
             console.error('Error deleting conversation:', error);
-            this.message.error('Failed to delete conversation');
+            this.message.error(this.i18nSvc.fanyi('ai.chat.conversation.delete.failed'));
           }
         });
       }
@@ -228,14 +257,14 @@ export class ChatComponent implements OnInit, AfterViewChecked {
    * Send a message
    */
   sendMessage(): void {
-    if (!this.newMessage.trim() || this.isLoading) {
+    if (!this.newMessage.trim() || this.isSendingMessage) {
       return;
     }
 
     const userMessage: ChatMessage = {
       content: this.newMessage.trim(),
       role: 'user',
-      timestamp: new Date()
+      gmtCreate: new Date()
     };
 
     // Add user message to the messages list
@@ -243,22 +272,20 @@ export class ChatComponent implements OnInit, AfterViewChecked {
 
     const messageContent = this.newMessage.trim();
     this.newMessage = '';
-    this.isLoading = true;
+    this.isSendingMessage = true;
     this.cdr.detectChanges();
     this.scrollToBottom();
 
     // Check if this is a fallback conversation
-    if (this.currentConversation?.conversationId.startsWith('fallback-')) {
-      console.log('Fallback mode - showing offline message');
+    if (this.currentConversation?.id == 0) {
       setTimeout(() => {
         const offlineMessage: ChatMessage = {
-          content:
-            'I apologize, but the AI Chat service is currently unavailable. Please ensure the HertzBeat AI Agent module is running and try again later.',
+          content: this.i18nSvc.fanyi('ai.chat.offline.response'),
           role: 'assistant',
-          timestamp: new Date()
+          gmtCreate: new Date()
         };
         this.messages.push(offlineMessage);
-        this.isLoading = false;
+        this.isSendingMessage = false;
         this.cdr.detectChanges();
         this.scrollToBottom();
       }, 1000);
@@ -269,24 +296,21 @@ export class ChatComponent implements OnInit, AfterViewChecked {
     const assistantMessage: ChatMessage = {
       content: '',
       role: 'assistant',
-      timestamp: new Date()
+      gmtCreate: new Date()
     };
     this.messages.push(assistantMessage);
     this.cdr.detectChanges();
     this.scrollToBottom();
 
     // Send to AI service
-    console.log('Sending message to AI service:', messageContent);
-    this.aiChatService.streamChat(messageContent, this.currentConversation?.conversationId).subscribe({
+    this.aiChatService.streamChat(messageContent, this.currentConversation?.id).subscribe({
       next: chunk => {
-        console.log('Received stream chunk:', chunk);
-
         // Find the last assistant message and append content
         const lastMessage = this.messages[this.messages.length - 1];
         if (lastMessage && lastMessage.role === 'assistant') {
           // Accumulate the content for streaming effect
           lastMessage.content += chunk.content;
-          lastMessage.timestamp = chunk.timestamp instanceof Date ? chunk.timestamp : new Date();
+          lastMessage.gmtCreate = chunk.gmtCreate;
 
           this.cdr.detectChanges();
           this.scrollToBottom();
@@ -294,7 +318,7 @@ export class ChatComponent implements OnInit, AfterViewChecked {
       },
       error: error => {
         console.error('Error in chat stream:', error);
-        this.message.error(`Failed to get AI response: ${error.status} ${error.statusText || error.message}`);
+        this.message.error(`${this.i18nSvc.fanyi('ai.chat.error.chat.response')}: ${error.status} ${error.statusText || error.message}`);
 
         // Remove the empty assistant message and add error message
         if (
@@ -306,26 +330,26 @@ export class ChatComponent implements OnInit, AfterViewChecked {
         }
 
         const errorMessage: ChatMessage = {
-          content: 'Sorry, there was an error processing your request. Please check if the AI Agent service is running and try again.',
+          content: this.i18nSvc.fanyi('ai.chat.error.processing'),
           role: 'assistant',
-          timestamp: new Date()
+          gmtCreate: new Date()
         };
         this.messages.push(errorMessage);
-        this.isLoading = false;
+        this.isSendingMessage = false;
         this.cdr.detectChanges();
         this.scrollToBottom();
       },
       complete: () => {
-        this.isLoading = false;
+        this.isSendingMessage = false;
         this.cdr.detectChanges();
 
         // Refresh current conversation to get updated data (only if not fallback)
-        if (this.currentConversation && !this.currentConversation.conversationId.startsWith('fallback-')) {
-          this.aiChatService.getConversation(this.currentConversation.conversationId).subscribe({
+        if (this.currentConversation && this.currentConversation.id !== 0) {
+          this.aiChatService.getConversation(this.currentConversation.id).subscribe({
             next: response => {
               if (response.code === 0 && response.data) {
                 // Update conversation in the list
-                const index = this.conversations.findIndex(c => c.conversationId === response.data!.conversationId);
+                const index = this.conversations.findIndex(c => c.id === response.data!.id);
                 if (index >= 0) {
                   this.conversations[index] = response.data;
                 }
@@ -361,23 +385,24 @@ export class ChatComponent implements OnInit, AfterViewChecked {
   /**
    * Format conversation title
    */
-  getConversationTitle(conversation: ConversationDto): string {
+  getConversationTitle(conversation: ChatConversation): string {
+    if (conversation.title) {
+      return conversation.title;
+    }
     if (conversation.messages && conversation.messages.length > 0) {
       const firstUserMessage = conversation.messages.find(m => m.role === 'user');
       if (firstUserMessage) {
         return firstUserMessage.content.length > 30 ? `${firstUserMessage.content.substring(0, 30)}...` : firstUserMessage.content;
       }
     }
-    return `Conversation ${conversation.conversationId.substring(0, 8)}`;
+    return `Conversation ${conversation.id}`;
   }
 
   /**
    * Format time
    */
-  formatTime(date: Date): string {
-    if (!(date instanceof Date)) {
-      date = new Date(date);
-    }
+  formatTime(date: any): string {
+    date = new Date(date);
     return date.toLocaleTimeString('en-US', {
       hour: '2-digit',
       minute: '2-digit'
@@ -407,13 +432,19 @@ export class ChatComponent implements OnInit, AfterViewChecked {
   }
 
   /**
-   * Scroll to bottom of messages
+   * Scroll to bottom of messages with smooth animation
    */
   private scrollToBottom(): void {
     try {
       if (this.messagesContainer) {
         const element = this.messagesContainer.nativeElement;
-        element.scrollTop = element.scrollHeight;
+        // Use requestAnimationFrame for better performance
+        requestAnimationFrame(() => {
+          element.scrollTo({
+            top: element.scrollHeight,
+            behavior: 'smooth'
+          });
+        });
       }
     } catch (err) {
       console.error('Error scrolling to bottom:', err);
@@ -444,12 +475,7 @@ export class ChatComponent implements OnInit, AfterViewChecked {
               this.aiProviderConfig.model = defaultProvider.defaultModel;
             }
           }
-
-          if (response.data.enable) {
-            this.loadConversations();
-          } else {
-            this.showAiProviderConfigDialog(response.data.error);
-          }
+          // Don't load conversations here anymore - they're loaded in ngOnInit
         } else {
           // Initialize with default values if no config exists
           this.aiProviderConfig = new ModelProviderConfig();
@@ -470,26 +496,26 @@ export class ChatComponent implements OnInit, AfterViewChecked {
   showAiProviderConfigDialog(error?: string): void {
     let contentMessage = `
       <div style="margin-bottom: 16px;">
-        <p>To use AI Agent Chat, please configure your Model Provider.</p>
+        <p>${this.i18nSvc.fanyi('ai.chat.config.required.content')}</p>
     `;
 
     if (error) {
       contentMessage += `
         <div style="margin-bottom: 12px; padding: 8px; background: #fff2f0; border: 1px solid #ffccc7; border-radius: 4px;">
-          <strong>Configuration Issue:</strong> ${error}
+          <strong>${this.i18nSvc.fanyi('ai.chat.config.required.error')}</strong> ${error}
         </div>
       `;
     }
 
     const modalRef = this.modal.create({
-      nzTitle: 'Ai Model Provider Configuration Required',
+      nzTitle: this.i18nSvc.fanyi('ai.chat.config.required.title'),
       nzContent: contentMessage,
       nzWidth: 600,
       nzClosable: false,
       nzMaskClosable: false,
       nzFooter: [
         {
-          label: 'Configure Here',
+          label: this.i18nSvc.fanyi('ai.chat.config.required.button'),
           type: 'primary',
           onClick: () => {
             this.showConfigModal = true;
@@ -520,52 +546,47 @@ export class ChatComponent implements OnInit, AfterViewChecked {
    */
   onSaveAiProviderConfig(): void {
     if (!this.aiProviderConfig.apiKey?.trim()) {
-      this.message.error('Please enter API Key');
+      this.message.error(this.i18nSvc.fanyi('ai.chat.error.api.key'));
       return;
     }
 
     if (!this.aiProviderConfig.code?.trim()) {
-      this.message.error('Please select a provider');
+      this.message.error(this.i18nSvc.fanyi('ai.chat.error.provider'));
       return;
     }
 
     if (!this.aiProviderConfig.baseUrl?.trim()) {
-      this.message.error('Please enter Base URL');
+      this.message.error(this.i18nSvc.fanyi('ai.chat.error.base.url'));
       return;
     }
 
     if (!this.aiProviderConfig.model?.trim()) {
-      this.message.error('Please enter Model');
+      this.message.error(this.i18nSvc.fanyi('ai.chat.error.model'));
       return;
     }
 
-    // Always enable when saving an API key
-    this.aiProviderConfig.enable = true;
-    this.aiProviderConfig.status = true;
-
     this.configLoading = true;
-    this.message.info('Validating API key...', { nzDuration: 2000 });
 
     this.generalConfigSvc.saveModelProviderConfig(this.aiProviderConfig).subscribe({
       next: response => {
         this.configLoading = false;
         if (response.code === 0) {
-          this.message.success('Model Provider configuration saved successfully!');
+          this.message.success(this.i18nSvc.fanyi('ai.chat.config.save.success'));
           this.showConfigModal = false;
-          this.isOpenAiConfigured = true;
+          this.isAiProviderConfigured = true;
           this.loadConversations();
         } else {
           // Check if it's a validation error
           if (response.msg.includes('validation failed')) {
-            this.message.error(`❌ API Key validation failed: ${response.msg}`, { nzDuration: 5000 });
+            this.message.error(`${this.i18nSvc.fanyi('ai.chat.config.validation.failed')} ${response.msg}`, { nzDuration: 5000 });
           } else {
-            this.message.error(`Failed to save configuration: ${response.msg}`);
+            this.message.error(`${this.i18nSvc.fanyi('ai.chat.config.save.failed')} ${response.msg}`);
           }
         }
       },
       error: error => {
         this.configLoading = false;
-        this.message.error(`Failed to save configuration: ${error.message}`);
+        this.message.error(`${this.i18nSvc.fanyi('ai.chat.config.save.failed')} ${error.message}`);
       }
     });
   }
diff --git a/web-app/src/app/shared/services/ai-chat-modal.service.ts b/web-app/src/app/shared/services/ai-chat-modal.service.ts
index e84e5d6274..d354569482 100644
--- a/web-app/src/app/shared/services/ai-chat-modal.service.ts
+++ b/web-app/src/app/shared/services/ai-chat-modal.service.ts
@@ -30,7 +30,7 @@ export class AiChatModalService {
 
   constructor(private modalService: NzModalService) {}
 
-  openChatModal(): void {
+  openChatModal(initialMessage?: string): void {
     if (this.currentModal) {
       this.currentModal.destroy();
     }
@@ -58,6 +58,10 @@ export class AiChatModalService {
         return true;
       }
     });
+
+    if (initialMessage && this.currentModal.componentInstance) {
+      this.currentModal.componentInstance.initialMessage = initialMessage;
+    }
   }
 
   closeChatModal(): void {
diff --git a/web-app/src/assets/app-data.json b/web-app/src/assets/app-data.json
index 957ab5e097..b232d4fd00 100644
--- a/web-app/src/assets/app-data.json
+++ b/web-app/src/assets/app-data.json
@@ -218,6 +218,13 @@
       "group": true,
       "hideInBreadcrumb": true,
       "children": [
+        {
+          "text": "mcp-server",
+          "i18n": "menu.advanced.mcp-server",
+          "icon": "anticon-compass",
+          "target": "_blank",
+          "externalLink": "https://hertzbeat.apache.org/docs/help/mcp_sse_server"
+        },
         {
           "text": "status",
           "i18n": "menu.advanced.status",
diff --git a/web-app/src/assets/i18n/en-US.json b/web-app/src/assets/i18n/en-US.json
index e05785581e..8ce91bfc45 100644
--- a/web-app/src/assets/i18n/en-US.json
+++ b/web-app/src/assets/i18n/en-US.json
@@ -692,6 +692,7 @@
   "menu.advanced.labels": "Labels",
   "menu.advanced.plugins": "Plugins",
   "menu.advanced.status": "Status",
+  "menu.advanced.mcp-server": "MCP Server",
   "menu.alert": "Alerting",
   "menu.alert.center": "Alarms",
   "menu.alert.converge": "Converge",
@@ -705,7 +706,7 @@
   "menu.dashboard": "Dashboard",
   "menu.extras": "More",
   "menu.extras.about": "About",
-  "menu.extras.ai.chat": "AI Agent Chat",
+  "menu.extras.ai.chat": "HertzBeat AI",
   "menu.extras.help": "Help",
   "menu.extras.setting": "Setting",
   "menu.extras.settings": "Settings",
@@ -840,6 +841,7 @@
   "monitor.holdingRegisterAddresses.tip": "Input RegisterAddress",
   "monitor.host": "Target Host",
   "monitor.host.tip": "The target peer ip or domain name",
+  "monitor.help": "Monitoring and management page, you can check the metric data and manage monitoring tasks here. The status of normal service is",
   "monitor.icon.bigdata": "dot-chart",
   "monitor.icon.cache": "group",
   "monitor.icon.center": "laptop",
@@ -1061,5 +1063,60 @@
   "ai.bot.input.placeholder": "Please enter a question...",
   "ai.bot.send": "Send",
   "ai.bot.connect-fail": "Sorry, there was an issue connecting to the AI assistant. Please try again later.",
-  "monitor.help": "Monitoring and management page, you can check the metric data and manage monitoring tasks here. The status of normal service is"
+  "ai.chat.assistant": "AI Assistant",
+  "ai.chat.config.api-key": "API Key",
+  "ai.chat.config.api-key.help": "Your Provider API key. The key will be validated when saved.",
+  "ai.chat.config.api-key.required": "API Key is required",
+  "ai.chat.config.base-url": "Base URL",
+  "ai.chat.config.base-url.help": "Custom API endpoint URL. Leave empty to use default for selected provider.",
+  "ai.chat.config.cancel": "Cancel",
+  "ai.chat.config.model": "Model",
+  "ai.chat.config.model.help": "Model name to use. Leave empty to use default for selected provider.",
+  "ai.chat.config.provider": "AI Provider",
+  "ai.chat.config.provider.help": "Choose your AI provider (OpenAI, ZhiPu, or ZAI)",
+  "ai.chat.config.provider.required": "Please select an AI provider",
+  "ai.chat.config.reset": "Reset to default values",
+  "ai.chat.config.save": "Save",
+  "ai.chat.config.title": "AI Provider Configuration",
+  "ai.chat.input.hint": "Press Enter to send, Shift+Enter for new line",
+  "ai.chat.input.placeholder": "Ask me anything about observability...",
+  "ai.chat.loading": "Loading conversation history...",
+  "ai.chat.modify-api-key": "Modify API Key",
+  "ai.chat.new-chat": "New Chat",
+  "ai.chat.thinking": "AI is thinking...",
+  "ai.chat.title": "HertzBeat AI",
+  "ai.chat.typing": "Typing...",
+  "ai.chat.user": "You",
+  "ai.chat.welcome.capabilities.alerts": "View and analyze alerts with comprehensive filtering",
+  "ai.chat.welcome.capabilities.config": "Configure alert rules and thresholds",
+  "ai.chat.welcome.capabilities.manage": "Query and manage monitors by status, type, or labels",
+  "ai.chat.welcome.capabilities.metrics": "Access real-time and historical metrics data",
+  "ai.chat.welcome.capabilities.monitor": "Add new monitors for websites, APIs, databases, and services",
+  "ai.chat.welcome.capabilities.troubleshoot": "Troubleshoot performance issues across your infrastructure",
+  "ai.chat.welcome.description": "I'm your intelligent observability companion, ready to help you manage and optimize your infrastructure observability. You can ask me to:",
+  "ai.chat.welcome.title": "Welcome to HertzBeat AI!",
+  "ai.chat.conversation.created": "New conversation created",
+  "ai.chat.conversation.delete.title": "Delete Conversation",
+  "ai.chat.conversation.delete.content": "Are you sure you want to delete this conversation?",
+  "ai.chat.conversation.delete.confirm": "Delete",
+  "ai.chat.conversation.delete.success": "Conversation deleted",
+  "ai.chat.conversation.delete.failed": "Failed to delete conversation",
+  "ai.chat.config.required.title": "AI Model Provider Configuration Required",
+  "ai.chat.config.required.content": "To use AI Agent Chat, please configure your Model Provider.",
+  "ai.chat.config.required.error": "Configuration Issue:",
+  "ai.chat.config.required.button": "Configure Here",
+  "ai.chat.config.validation.failed": "❌ API Key validation failed:",
+  "ai.chat.config.save.success": "Model Provider configuration saved successfully!",
+  "ai.chat.config.save.failed": "Failed to save configuration:",
+  "ai.chat.error.api.key": "Please enter API Key",
+  "ai.chat.error.provider": "Please select a provider",
+  "ai.chat.error.base.url": "Please enter Base URL",
+  "ai.chat.error.model": "Please enter Model",
+  "ai.chat.error.conversations.load": "Failed to load conversations:",
+  "ai.chat.error.conversation.create": "Failed to create new conversation:",
+  "ai.chat.error.conversation.history": "Failed to load conversation history",
+  "ai.chat.error.chat.response": "Failed to get AI response:",
+  "ai.chat.error.processing": "Sorry, there was an error processing your request. Please check if the AI Agent service is running and try again.",
+  "ai.chat.offline.mode": "AI Chat service unavailable. Running in offline mode.",
+  "ai.chat.offline.response": "I apologize, but the AI Chat service is currently unavailable. Please ensure the HertzBeat AI module is running and try again later."
 }
diff --git a/web-app/src/assets/i18n/ja-JP.json b/web-app/src/assets/i18n/ja-JP.json
index c0961caa50..653a693c72 100644
--- a/web-app/src/assets/i18n/ja-JP.json
+++ b/web-app/src/assets/i18n/ja-JP.json
@@ -683,6 +683,7 @@
   "menu.advanced.labels": "ラベル",
   "menu.advanced.plugins": "プラグイン",
   "menu.advanced.status": "ステータス",
+  "menu.advanced.mcp-server": "MCPサーバー",
   "menu.alert": "アラート設定",
   "menu.alert.center": "アラーム",
   "menu.alert.converge": "収束",
@@ -696,7 +697,7 @@
   "menu.dashboard": "ダッシュボード",
   "menu.extras": "その他",
   "menu.extras.about": "概要",
-  "menu.extras.ai.chat": "AIアシスタント",
+  "menu.extras.ai.chat": "HertzBeat AI",
   "menu.extras.help": "ヘルプ",
   "menu.extras.setting": "設定",
   "menu.extras.settings": "設定",
@@ -1036,5 +1037,61 @@
   "ai.bot.greeting": "こんにちは!私はAIアシスタントです。何かお手伝いできることはありますか?",
   "ai.bot.input.placeholder": "質問を入力してください...",
   "ai.bot.send": "送信",
-  "ai.bot.connect-fail": "申し訳ありません、AIアシスタントへの接続中に問題が発生しました。後ほど再度お試しください。"
+  "ai.bot.connect-fail": "申し訳ありません、AIアシスタントへの接続中に問題が発生しました。後ほど再度お試しください。",
+  "ai.chat.assistant": "AI アシスタント",
+  "ai.chat.config.api-key": "API キー",
+  "ai.chat.config.api-key.help": "プロバイダーの API キー。保存時にキーが検証されます。",
+  "ai.chat.config.api-key.required": "API キーが必要です",
+  "ai.chat.config.base-url": "ベース URL",
+  "ai.chat.config.base-url.help": "カスタム API エンドポイント URL。選択したプロバイダーのデフォルトを使用する場合は空のままにしてください。",
+  "ai.chat.config.cancel": "キャンセル",
+  "ai.chat.config.model": "モデル",
+  "ai.chat.config.model.help": "使用するモデル名。選択したプロバイダーのデフォルトを使用する場合は空のままにしてください。",
+  "ai.chat.config.provider": "AI プロバイダー",
+  "ai.chat.config.provider.help": "AI プロバイダーを選択してください(OpenAI、ZhiPu、または ZAI)",
+  "ai.chat.config.provider.required": "AI プロバイダーを選択してください",
+  "ai.chat.config.reset": "デフォルト値にリセット",
+  "ai.chat.config.save": "保存",
+  "ai.chat.config.title": "AI プロバイダー設定",
+  "ai.chat.input.hint": "Enter で送信、Shift+Enter で改行",
+  "ai.chat.input.placeholder": "可観測性について何でもお聞きください...",
+  "ai.chat.loading": "会話履歴を読み込み中...",
+  "ai.chat.modify-api-key": "API キーを変更",
+  "ai.chat.new-chat": "新しいチャット",
+  "ai.chat.thinking": "AI が考え中...",
+  "ai.chat.title": "HertzBeat AI",
+  "ai.chat.typing": "入力中...",
+  "ai.chat.user": "あなた",
+  "ai.chat.welcome.capabilities.alerts": "包括的なフィルタリングでアラートを表示・分析",
+  "ai.chat.welcome.capabilities.config": "アラートルールと閾値を設定",
+  "ai.chat.welcome.capabilities.manage": "ステータス、タイプ、ラベルでモニターを照会・管理",
+  "ai.chat.welcome.capabilities.metrics": "リアルタイムおよび履歴メトリクスデータにアクセス",
+  "ai.chat.welcome.capabilities.monitor": "ウェブサイト、API、データベース、サービスの新しいモニターを追加",
+  "ai.chat.welcome.capabilities.troubleshoot": "インフラストラクチャ全体のパフォーマンス問題をトラブルシューティング",
+  "ai.chat.welcome.description": "私はあなたのインテリジェントな可観測性パートナーです。インフラストラクチャ可観測性の管理と最適化をお手伝いします。以下のことをお尋ねいただけます:",
+  "ai.chat.welcome.title": "HertzBeat AI へようこそ!",
+  "ai.chat.conversation.created": "新しい会話が作成されました",
+  "ai.chat.conversation.delete.title": "会話を削除",
+  "ai.chat.conversation.delete.content": "この会話を削除してもよろしいですか?",
+  "ai.chat.conversation.delete.confirm": "削除",
+  "ai.chat.conversation.delete.success": "会話が削除されました",
+  "ai.chat.conversation.delete.failed": "会話の削除に失敗しました",
+  "ai.chat.config.required.title": "AI モデルプロバイダー設定が必要です",
+  "ai.chat.config.required.content": "AI エージェントチャットを使用するには、モデルプロバイダーを設定してください。",
+  "ai.chat.config.required.error": "設定の問題:",
+  "ai.chat.config.required.button": "ここで設定",
+  "ai.chat.config.validation.failed": "❌ API キーの検証に失敗しました:",
+  "ai.chat.config.save.success": "モデルプロバイダー設定が正常に保存されました!",
+  "ai.chat.config.save.failed": "設定の保存に失敗しました:",
+  "ai.chat.error.api.key": "API キーを入力してください",
+  "ai.chat.error.provider": "プロバイダーを選択してください",
+  "ai.chat.error.base.url": "ベース URL を入力してください",
+  "ai.chat.error.model": "モデルを入力してください",
+  "ai.chat.error.conversations.load": "会話の読み込みに失敗しました:",
+  "ai.chat.error.conversation.create": "新しい会話の作成に失敗しました:",
+  "ai.chat.error.conversation.history": "会話履歴の読み込みに失敗しました",
+  "ai.chat.error.chat.response": "AI の応答の取得に失敗しました:",
+  "ai.chat.error.processing": "申し訳ございませんが、リクエストの処理中にエラーが発生しました。AI エージェントサービスが実行されているかご確認の上、再度お試しください。",
+  "ai.chat.offline.mode": "AI チャットサービスが利用できません。オフラインモードで実行中です。",
+  "ai.chat.offline.response": "申し訳ございませんが、AI チャットサービスは現在利用できません。HertzBeat AI モジュールが実行されていることを確認して、後でもう一度お試しください。"
 }
diff --git a/web-app/src/assets/i18n/pt-BR.json b/web-app/src/assets/i18n/pt-BR.json
index d1cd0915fa..32107405bd 100644
--- a/web-app/src/assets/i18n/pt-BR.json
+++ b/web-app/src/assets/i18n/pt-BR.json
@@ -1,286 +1,4 @@
 {
-  "menu": {
-    "main": "Principal",
-    "lang": "Idioma",
-    "dashboard": "Painel",
-    "search.placeholder": "Pesquisar: Tarefa de Monitoramento: Nome, Host, etc",
-    "fullscreen": "Tela Cheia",
-    "fullscreen.exit": "Sair",
-    "clear.local.storage": "Limpar Armazenamento Local",
-    "monitor": {
-      "": "Monitoramento",
-      "center": "Centro de Monitoramento",
-      "bulletin": "Boletim",
-      "service": "Monitor de Serviço",
-      "db": "Monitor de Banco de Dados",
-      "os": "Monitor de Sistema Operacional",
-      "mid": "Monitor de Middleware",
-      "cn": "Nativo da Nuvem",
-      "network": "Monitor de Rede",
-      "custom": "Monitor Personalizado",
-      "prometheus": "Tarefa Prometheus",
-      "program": "Monitor de Programa",
-      "webserver": "Monitor de Servidor Web",
-      "cache": "Monitor de Cache",
-      "bigdata": "Monitor de Big Data",
-      "promql": "Consulta de Dados",
-      "llm": "AI LLM",
-      "server": "Monitor de Servidor"
-    },
-    "account": {
-      "": "Pessoal",
-      "center": "Centro Pessoal",
-      "settings": "Configurações da Conta",
-      "security": "Configurações de Segurança",
-      "binding": "Vinculação de Conta",
-      "trigger": "Disparar Erro",
-      "logout": "Sair"
-    },
-    "alert": {
-      "": "Alertas",
-      "center": "Centro de Alarmes",
-      "converge": "Convergência de Alarmes",
-      "setting": "Regra de Limite",
-      "silence": "Silenciar Alarme",
-      "dispatch": "Notificação"
-    },
-    "advanced": {
-      "": "Avançado",
-      "collector": "Cluster de Coletores",
-      "tags": "Gerenciar Tags",
-      "define": "Modelo de Monitoramento",
-      "status": "Página de Status",
-      "plugins": "Gerenciar Plugins"
-    },
-    "extras": {
-      "": "Mais",
-      "help": "Centro de Ajuda",
-      "setting": "Configuração",
-      "settings": "Configurações",
-      "about": "Sobre"
-    },
-    "more": "Mais"
-  },
-  "monitor": {
-    "": "Monitor",
-    "availability": "Disponibilidade do Monitor",
-    "name": "Nome da Tarefa",
-    "name.tip": "Nome da tarefa de monitoramento",
-    "host": "Host de Destino",
-    "host.tip": "O IP ou domínio do peer monitorado",
-    "description": "Descrição",
-    "description.tip": "Descrição e observações",
-    "intervals": "Intervalos",
-    "intervals.tip": "Intervalo de tempo para coleta periódica de dados, em segundos",
-    "question.link": "https://hertzbeat.apache.org/docs/help/issue/",
-    "dashboard.alerts.title": "Lista de Alarmes Recentes",
-    "dashboard.alerts.title-no": "Alarmes Pendentes Recentes",
-    "dashboard.alerts.no": "Nenhum Alarme Pendente",
-    "dashboard.alerts.enter": "Ir para o Centro de Alarmes",
-    "dashboard.alerts.distribute": "A Distribuição dos Alarmes",
-    "dashboard.alerts.num": "Número de Alarmes",
-    "dashboard.alerts.deal": "Tratamento de Alarmes",
-    "dashboard.alerts.deal-percent": "Taxa de Tratamento",
-    "dashboard.monitors.total": "Total de Monitores",
-    "dashboard.monitors.title": "Visão Geral do Monitoramento",
-    "dashboard.monitors.sub-title": "A Distribuição dos Monitores",
-    "dashboard.monitors.formatter": " Monitores ",
-    "dashboard.monitors.distribute": "Distribuição do Monitor",
-    "menu.link.question": "FAQ",
-    "menu.link.guild": "Guia do Usuário",
-    "validation.email.invalid": "Email inválido!",
-    "validation.phone.invalid": "Número de telefone inválido!",
-    "validation.verification-code.invalid": "Código de verificação inválido, deve ter 6 dígitos!",
-    "validation.required": "Por favor, preencha os campos obrigatórios! ",
-    "app.theme.default": "Tema Claro",
-    "app.theme.dark": "Tema Escuro",
-    "app.theme.compact": "Tema Compacto",
-    "app.role.admin": "administrador",
-    "app.lock": "Desbloquear",
-    "app.lock.placeholder": "Digite qualquer coisa para desbloquear",
-    "app.passport.desc": "Sistema de observabilidad en tiempo real de código abierto",
-    "app.passport.intro-1": "Código Aberto, Distribuído",
-    "app.passport.intro-2": "Monitoramento em Tempo Real",
-    "app.login.message-need-identifier": "Por favor, insira seu nome de usuário",
-    "app.login.message-need-credential": "Por favor, insira a senha",
-    "app.login.message-invalid-credentials": "Nome de usuário ou senha inválidos",
-    "app.login.need-change-password": "Por favor, atualize a senha inicial padrão em tempo hábil!",
-    "app.login.tab-login-credentials": "Entrar no HertzBeat",
-    "app.login.remember-me": "Lembrar de mim",
-    "app.login.login": "Entrar",
-    "app.login.notify": "Por favor, faça login!",
-    "app.login.explore.cloud": "Explorar Nuvem",
-    "app.login.explore.cloud.detail": "Clique para Explorar a Nuvem HertzBeat",
-    "tag.new": "Nova Tag",
-    "tag.edit": "Editar Tag",
-    "tag.search": "Pesquisar Tag",
-    "tag.delete": "Excluir Tag",
-    "tag": "Tag",
-    "tag.setting": "Tags",
-    "tag.id": "ID",
-    "tag.name": "Nome da Tag",
-    "tag.value": "Valor da Tag",
-    "tag.color": "Cor",
-    "tag.description": "Descrição",
-    "tag.update-time": "Tempo de Atualização",
-    "tag.display": "Exibir",
-    "tag.bind": "Vincular Tags",
-    "tag.bind.tip": "Você pode usar tags para gerenciamento de classificação. Ex: atribuir tags a recursos em ambiente de produção e teste.",
-    "tag.help": "As tags estão em todos os lugares no HertzBeat. Podemos aplicar tags no agrupamento de recursos, correspondência de tags sob regras e outros. [Gerenciamento de Tags] é usado para gerenciamento unificado de tags, incluindo adição, exclusão, edição, etc. <br>Você pode usar tags para classificar e gerenciar recursos de monitoramento, como vincular etiquetas para ambientes de produção e teste separadamente.",
-    "tag.help.link": "https://hertzbeat.apache.org/zh-cn/docs/",
-    "plugin.help": "No HertzBeat, podemos usar o mecanismo de plugin para realizar algumas outras operações após o alarme, exceto notificação. O gerenciamento de plugins é usado para gerenciamento unificado de plugins, incluindo upload e operações de habilitar/desabilitar.<br>Por exemplo, você pode usar o mecanismo de plugin para executar scripts específicos ou SQL após a ocorrência do alarme.",
-    "plugin.help.link": "https://hertzbeat.apache.org/docs/help/plugin",
-    "plugin.upload": "Carregar Plugin",
-    "plugin.name": "Nome do Plugin",
-    "plugin.type": "Tipo do Plugin",
-    "plugin.status": "Status Habilitado",
-    "plugin.jar.file": "Arquivo Jar",
-    "plugin.delete": "Excluir Plugin",
-    "plugin.type.POST_ALERT": "PÓS ALERTA",
-    "plugin.type.POST_COLLECT": "PÓS COLETA",
-    "plugin.search": "Pesquisar plugins",
-    "plugin.edit": "Editar plugin",
-    "plugin.param.edit": "Editar Parâmetros",
-    "define.help": "Os modelos de monitoramento definem cada tipo de monitoramento, variável de parâmetro, informações de métricas, protocolo de coleta, etc. Você pode selecionar um modelo de monitoramento existente no menu suspenso e fazer modificações de acordo com suas próprias necessidades. A área inferior esquerda é a área de comparação e a área inferior direita é o local de edição. <br> Você também pode clicar em \"Novo Tipo de Monitor\" para definir um novo tipo personalizado. Atu [...]
-    "define.help.link": "https://hertzbeat.apache.org/zh-cn/docs/advanced/extend-point/",
-    "define.save-apply": "Salvar e Aplicar",
-    "define.delete": "Excluir {{app}}",
-    "define.delete.confirm": "Confirme se deseja excluir o tipo de monitoramento {{app}}? Este tipo de monitoramento não poderá ser adicionado após a exclusão.",
-    "define.new": "Novo Tipo de Monitor",
-    "define.new.code": "# Por favor, defina um novo tipo de monitoramento escrevendo o conteúdo YML aqui, consulte o documento: https://hertzbeat.apache.org/docs/advanced/extend-point ",
-    "define.save-apply.no-code": "O conteúdo da definição do tipo de monitoramento não pode estar vazio.",
-    "define.save-apply.confirm": "Confirme se deseja atualizar e aplicar a definição do monitor? Isso afetará o que você monitora.",
-    "define.hide-true.tip": "Não exibido no menu principal, se deseja exibi-lo",
-    "define.hide-true.confirm": "Confirme se deseja exibir este menu?",
-    "define.hide-false.tip": "Já exibido no menu principal, se deseja ocultá-lo",
-    "define.hide-false.confirm": "Confirme se deseja ocultar este menu?",
-    "label": "Rótulo",
-    "label.bind": "Etiqueta de ligação",
-    "label.bind.tip": "Você pode usar tags para classificar e gerenciar recursos de monitoramento, como vincular tags para ambiente de produção e ambiente de teste a recursos.",
-    "label.color": "Cor",
-    "label.delete": "Excluir etiqueta",
-    "label.description": "Descrição da tag",
-    "label.display": "Efeito",
-    "label.edit": "Editar tags",
-    "label.id": "ID",
-    "label.name": "Nome da tag",
-    "label.new": "Tags adicionadas",
-    "label.search": "Tags de pesquisa",
-    "label.setting": "Rótulo",
-    "label.value": "Valor da etiqueta",
-    "labels.help": "As tags estão por toda parte, podemos aplicar tags ao agrupamento de recursos, correspondência de tags sob regras e outros cenários. O gerenciamento de tags é usado para gerenciar e manter tags de maneira unificada, incluindo adicionar, excluir, editar e outras operações. <br> Por exemplo: você pode usar tags para classificar e gerenciar recursos de monitoramento, vincular as tags do ambiente de produção e testar o ambiente dos recursos e combinar notificadores difere [...]
-    "labels.help.link": "https://hertzbeat.apache.org/docs/",
-    "settings.server": "Configuração do Servidor de Mensagens",
-    "settings.server.email": "Servidor de Email",
-    "settings.server.email.setting": "Configurar Servidor de Email",
-    "settings.server.sms": "Servidor de SMS",
-    "settings.server.sms.setting": "Configurar Servidor de SMS",
-    "settings.system-config": "Configuração do Sistema",
-    "settings.system-config.locale": "Idioma do Sistema",
-    "settings.system-config.locale.zh_CN": "Chinês Simplificado(zh_CN)",
-    "settings.system-config.locale.zh_TW": "Chinês Tradicional(zh_TW)",
-    "settings.system-config.locale.en_US": "Inglês(en_US)",
-    "settings.system-config.locale.pt_BR": "Português(pt_BR)",
-    "settings.system-config.timezone": "Fuso Horário do Sistema",
-    "settings.system-config.theme": "Tema do Sistema",
-    "settings.system-config.theme.default": "Tema Padrão",
-    "settings.system-config.theme.dark": "Tema Escuro",
-    "settings.system-config.theme.compact": "Tema Compacto",
-    "settings.system-config.ok": "Confirmar Atualização",
-    "settings.object-store": "Configuração do Servidor de Arquivos",
-    "settings.object-store.type": "Provedor do Servidor de Arquivos",
-    "settings.object-store.type.file": "Arquivo local",
-    "settings.object-store.type.database": "Banco de dados local (padrão)",
-    "settings.object-store.type.obs": "HUAWEI CLOUD OBS",
-    "settings.object-store.obs.accessKey": "AccessKey",
-    "settings.object-store.obs.accessKey.placeholder": "Access Key ID da HUAWEI CLOUD",
-    "settings.object-store.obs.secretKey": "SecretKey",
-    "settings.object-store.obs.secretKey.placeholder": "Access Key Secret da HUAWEI CLOUD",
-    "settings.object-store.obs.bucketName": "Bucket",
-    "settings.object-store.obs.bucketName.placeholder": "O nome do bucket que você criou na HUAWEI CLOUD OBS",
-    "settings.object-store.obs.endpoint": "EndPoint",
-    "settings.object-store.obs.endpoint.placeholder": "Domínio da HUAWEI CLOUD OBS, excluindo o nome do bucket",
-    "settings.object-store.obs.savePath": "Caminho de Salvamento",
-    "settings.object-store.obs.savePath.placeholder": "Caminho para salvar o arquivo de backup, O valor padrão é hertzbeat.",
-    "collector": "Coletor",
-    "collector.tip": "Escolha qual coletor despachar para este monitoramento",
-    "collector.system.default": "Despacho Padrão do Sistema",
-    "collector.status.online": "Online",
-    "collector.status.offline": "Offline",
-    "category": {
-      "": "Categoria",
-      "server": "Monitor de Servidor",
-      "service": "Serviço",
-      "db": "Banco de Dados",
-      "os": "Sistema Operacional",
-      "mid": "Middleware",
-      "cn": "Nativo da Nuvem",
-      "network": "Rede",
-      "custom": "Personalizado",
-      "program": "Aplicação",
-      "webserver": "Servidor Web",
-      "cache": "Cache",
-      "bigdata": "Big Data",
-      "auto": "Tarefa Automática"
-    },
-    "app": {
-      "": "Tipo de Monitor",
-      "website": "Monitor de Site",
-      "api": "API HTTP",
-      "http": "API HTTP",
-      "ping": "Conexão PING",
-      "port": "Porta Disponível",
-      "mysql": "MySQL",
-      "oracle": "Oracle",
-      "redis": "Redis",
-      "fullsite": "Monitor de Mapa do Site"
-    },
-    "status": {
-      "": "Status da Tarefa",
-      "all": "Todos os Status",
-      "up": "Ativo",
-      "down": "Inativo",
-      "unreachable": "Inacessível",
-      "paused": "Pausado"
-    },
-    "grafana": {
-      "enabled.tip": "está habilitado, os dados de monitoramento serão exibidos no Grafana",
-      "enabled.label": "Habilitar Grafana",
-      "upload.tip": "Carregar arquivo de modelo do Grafana, suporta arquivo .json",
-      "upload.label": "Carregar Modelo do Grafana"
-    }
-  },
-  "alert": {
-    "": "Alerta",
-    "status": {
-      "": "Status do Alerta",
-      "all": "Todos os Status",
-      "0": "Pendente",
-      "2": "Restaurado",
-      "3": "Processado"
-    },
-    "priority": {
-      "": "Prioridade do Alarme",
-      "all": "Todas as Prioridades",
-      "0": "Emergência",
-      "1": "Crítico",
-      "2": "Aviso"
-    }
-  },
-  "bulletin": {
-    "new": "Novo Boletim",
-    "edit": "Editar Boletim",
-    "delete": "Excluir Boletim",
-    "batch.delete": "Excluir Boletins em Lote",
-    "name": "Nome do Boletim",
-    "name.placeholder": "Digite um nome personalizado para o boletim",
-    "monitor.type": "Tipo de Monitor",
-    "monitor.name": "Nome da Tarefa de Monitoramento",
-    "monitor.metrics": "Métricas de Monitoramento",
-    "help.content": "Boletim de monitoramento personalizado (beta), exibindo métricas selecionadas de um monitor específico em forma de tabela",
-    "help.link": ""
-  },
-  "question.link": "https://hertzbeat.apache.org/docs/help/issue/",
   "alert.setting.new": "Nova Regra de Limite",
   "alert.setting.new.periodic": "Nova Regra de Limite Periódica",
   "alert.setting.new.realtime": "Nova Regra de Limite em Tempo Real",
@@ -408,13 +126,13 @@
   "alert.center.confirm.mark-done": "Confirme se deseja marcar como processado!",
   "alert.center.confirm.mark-no-batch": "Confirme se deseja marcar como pendente em lote!",
   "alert.center.confirm.mark-no": "Confirme se deseja marcar como pendente!",
-  "alert.help.notice": "A notificação é usada para configurar o destinatário da mensagem de alarme e o método de recebimento. A mensagem de alarme será enviada ao destinatário de forma especificada (suporta email, discord, webhook, etc). <a href='https://hertzbeat.apache.org/zh-cn/docs/help/alert_webhook'>Clique aqui para ver os passos de configuração.</a>.<br>“<i>Modelo de Notificação</i>” é o modelo de estrutura de conteúdo da mensagem. O modelo embutido é usado por padrão ou você pode [...]
+  "alert.help.notice": "A notificação é usada para configurar o destinatário da mensagem de alarme e o método de recebimento. A mensagem de alarme será enviada ao destinatário de forma especificada (suporta email, discord, webhook, etc). <a href='https://hertzbeat.apache.org/zh-cn/docs/help/alert_webhook'>Clique aqui para ver os passos de configuração.</a>.<br>“<i>Modelo de Notificação</i>” é o modelo de estrutura de conteúdo da mensagem. O modelo embutido é usado por padrão ou você pode [...]
   "alert.help.notice.link": "https://hertzbeat.apache.org/docs/help/alert_email",
   "alert.help.converge": "A Convergência de Alarmes suporta a deduplicação e convergência de mensagens de alarme repetidas dentro de um período de tempo especificado. <br> Clique em \"<i>Nova Estratégia de Convergência</i>\" e configure o período de tempo para evitar um grande número de alarmes repetitivos que podem anestesiar o destinatário do alarme.",
   "alert.help.converge.link": "https://hertzbeat.apache.org",
   "alert.help.center": "O Centro de Alarmes é o centro de processamento de notificações para todas as mensagens de alarme disparadas, incluindo alarmes disparados por limites internos do sistema e informações de alarme acessadas através de canais de alarme externos de terceiros. <br> O Hertzbeat suporta operações em lote, como consulta de alarmes, marcação de processamento, não processados, exclusão de alarmes e limpeza.",
   "alert.help.center.link": "https://hertzbeat.apache.org/docs/help/guide",
-  "alert.help.setting": "As Regras de Limite são usadas para o gerenciamento de regras de limite de alarme para métricas. Clique em \"<i>Novo Limite</i>\" para configurar o limite de alarme para métricas de monitoramento. O Hertzbeat disparará alarmes com base no limite e nos dados das métricas.<br>Nota⚠\uFE0F: A mensagem de alarme que foi disparada pode ser verificada no [Centro de Alarmes], e você também pode configurar o método de notificação e os destinatários em [Notificação].",
+  "alert.help.setting": "As Regras de Limite são usadas para o gerenciamento de regras de limite de alarme para métricas. Clique em \"<i>Novo Limite</i>\" para configurar o limite de alarme para métricas de monitoramento. O Hertzbeat disparará alarmes com base no limite e nos dados das métricas.<br>Nota⚠️: A mensagem de alarme que foi disparada pode ser verificada no [Centro de Alarmes], e você também pode configurar o método de notificação e os destinatários em [Notificação].",
   "alert.help.setting.link": "https://hertzbeat.apache.org/docs/help/alert_threshold",
   "alert.help.silence": "O gerenciamento de Silêncio de Alarmes é usado quando você não quer ser perturbado durante a manutenção do sistema ou nos fins de semana. <br> Clique em \"<i>Nova Estratégia de Silêncio</i>\" e configure o período de tempo para bloquear mensagens para que você não seja perturbado durante os intervalos.",
   "alert.help.silence.link": "https://hertzbeat.apache.org/docs",
@@ -741,6 +459,7 @@
   "menu.advanced.labels": "Gerenciamento de tags",
   "menu.advanced.plugins": "Gerenciamento de plug-ins",
   "menu.advanced.status": "Página de status",
+  "menu.advanced.mcp-server": "Servidor MCP",
   "menu.alert": "Alarme",
   "menu.alert.center": "Central de alarme",
   "menu.alert.converge": "Convergência",
@@ -754,7 +473,7 @@
   "menu.dashboard": "Painel",
   "menu.extras": "Mais",
   "menu.extras.about": "sobre",
-  "menu.extras.ai.chat": "Assistente AI",
+  "menu.extras.ai.chat": "HertzBeat AI",
   "menu.extras.help": "Centro de ajuda",
   "menu.extras.setting": "configurar",
   "menu.extras.settings": "Configurações do sistema",
@@ -1138,6 +857,22 @@
   "define.hide-true.confirm": "Confirme se deseja exibir este menu?",
   "define.hide-false.tip": "Já exibido no menu principal, se deseja ocultá-lo",
   "define.hide-false.confirm": "Confirme se deseja ocultar este menu?",
+  "label": "Etiqueta",
+  "label.bind": "Vincular Etiquetas",
+  "label.bind.tip": "Você pode usar etiquetas para gerenciamento de classificação. Ex: atribuir etiquetas a recursos em ambiente de produção e teste.",
+  "label.color": "Cor",
+  "label.delete": "Excluir Etiqueta",
+  "label.description": "Descrição",
+  "label.display": "Exibir",
+  "label.edit": "Editar Etiqueta",
+  "label.id": "ID",
+  "label.name": "Nome da Etiqueta",
+  "label.new": "Nova Etiqueta",
+  "label.search": "Pesquisar Etiqueta",
+  "label.setting": "Etiquetas",
+  "label.value": "Valor da Etiqueta",
+  "labels.help": "Etiquetas estão em todos os lugares. Podemos aplicar etiquetas no agrupamento de recursos, correspondência de tags sob regras e outros. [Gerenciar Etiquetas] é usado para gerenciamento unificado de etiquetas, incluindo adicionar, excluir, editar, etc. <br>Você pode usar etiquetas para classificar e gerenciar recursos de monitoramento, como vincular etiquetas para ambientes de produção e teste separadamente.",
+  "labels.help.link": "https://hertzbeat.apache.org/zh-cn/docs/",
   "settings.server": "Configuração do Servidor de Mensagens",
   "settings.server.email": "Servidor de Email",
   "settings.server.email.setting": "Configurar Servidor de Email",
@@ -1321,5 +1056,175 @@
   "ai.bot.greeting": "Olá! Sou um assistente de IA. Como posso te ajudar?",
   "ai.bot.input.placeholder": "Digite sua pergunta...",
   "ai.bot.send": "Enviar",
-  "ai.bot.connect-fail": "Desculpe, ocorreu um problema ao conectar ao assistente de IA. Por favor, tente novamente mais tarde."
+  "ai.bot.connect-fail": "Desculpe, ocorreu um problema ao conectar ao assistente de IA. Por favor, tente novamente mais tarde.",
+  "ai.chat.assistant": "Assistente de IA",
+  "ai.chat.config.api-key": "Chave da API",
+  "ai.chat.config.api-key.help": "Sua chave da API do provedor. A chave será validada ao salvar.",
+  "ai.chat.config.api-key.required": "Chave da API é obrigatória",
+  "ai.chat.config.base-url": "URL Base",
+  "ai.chat.config.base-url.help": "URL personalizada do endpoint da API. Deixe vazio para usar o padrão do provedor selecionado.",
+  "ai.chat.config.cancel": "Cancelar",
+  "ai.chat.config.model": "Modelo",
+  "ai.chat.config.model.help": "Nome do modelo a ser usado. Deixe vazio para usar o padrão do provedor selecionado.",
+  "ai.chat.config.provider": "Provedor de IA",
+  "ai.chat.config.provider.help": "Escolha seu provedor de IA (OpenAI, ZhiPu ou ZAI)",
+  "ai.chat.config.provider.required": "Por favor, selecione um provedor de IA",
+  "ai.chat.config.reset": "Redefinir para valores padrão",
+  "ai.chat.config.save": "Salvar",
+  "ai.chat.config.title": "Configuração do Provedor de IA",
+  "ai.chat.input.hint": "Pressione Enter para enviar, Shift+Enter para nova linha",
+  "ai.chat.input.placeholder": "Pergunte-me qualquer coisa sobre observabilidade...",
+  "ai.chat.loading": "Carregando histórico da conversa...",
+  "ai.chat.modify-api-key": "Modificar Chave da API",
+  "ai.chat.new-chat": "Nova Conversa",
+  "ai.chat.thinking": "IA está pensando...",
+  "ai.chat.title": "HertzBeat AI",
+  "ai.chat.typing": "Digitando...",
+  "ai.chat.user": "Você",
+  "ai.chat.welcome.capabilities.alerts": "Visualizar e analisar alertas com filtragem abrangente",
+  "ai.chat.welcome.capabilities.config": "Configurar regras de alerta e limites",
+  "ai.chat.welcome.capabilities.manage": "Consultar e gerenciar monitores por status, tipo ou rótulos",
+  "ai.chat.welcome.capabilities.metrics": "Acessar dados de métricas em tempo real e históricos",
+  "ai.chat.welcome.capabilities.monitor": "Adicionar novos monitores para sites, APIs, bancos de dados e serviços",
+  "ai.chat.welcome.capabilities.troubleshoot": "Solucionar problemas de desempenho em toda sua infraestrutura",
+  "ai.chat.welcome.description": "Sou seu companheiro inteligente de observabilidade, pronto para ajudá-lo a gerenciar e otimizar a observabilidade de sua infraestrutura. Você pode me pedir para:",
+  "ai.chat.welcome.title": "Bem-vindo ao HertzBeat AI!",
+  "ai.chat.conversation.created": "Nova conversa criada",
+  "ai.chat.conversation.delete.title": "Excluir Conversa",
+  "ai.chat.conversation.delete.content": "Tem certeza de que deseja excluir esta conversa?",
+  "ai.chat.conversation.delete.confirm": "Excluir",
+  "ai.chat.conversation.delete.success": "Conversa excluída",
+  "ai.chat.conversation.delete.failed": "Falha ao excluir conversa",
+  "ai.chat.config.required.title": "Configuração do Provedor de Modelo de IA Necessária",
+  "ai.chat.config.required.content": "Para usar o Chat do Agente de IA, configure seu Provedor de Modelo.",
+  "ai.chat.config.required.error": "Problema de Configuração:",
+  "ai.chat.config.required.button": "Configurar Aqui",
+  "ai.chat.config.validation.failed": "❌ Falha na validação da chave da API:",
+  "ai.chat.config.save.success": "Configuração do Provedor de Modelo salva com sucesso!",
+  "ai.chat.config.save.failed": "Falha ao salvar configuração:",
+  "ai.chat.error.api.key": "Por favor, insira a Chave da API",
+  "ai.chat.error.provider": "Por favor, selecione um provedor",
+  "ai.chat.error.base.url": "Por favor, insira a URL Base",
+  "ai.chat.error.model": "Por favor, insira o Modelo",
+  "ai.chat.error.conversations.load": "Falha ao carregar conversas:",
+  "ai.chat.error.conversation.create": "Falha ao criar nova conversa:",
+  "ai.chat.error.conversation.history": "Falha ao carregar histórico da conversa",
+  "ai.chat.error.chat.response": "Falha ao obter resposta da IA:",
+  "ai.chat.error.processing": "Desculpe, houve um erro ao processar sua solicitação. Verifique se o serviço do Agente de IA está em execução e tente novamente.",
+  "ai.chat.offline.mode": "Serviço de Chat de IA indisponível. Executando em modo offline.",
+  "ai.chat.offline.response": "Peço desculpas, mas o serviço de Chat de IA está atualmente indisponível. Certifique-se de que o módulo HertzBeat AI está em execução e tente novamente mais tarde.",
+  "alert": "Alerta",
+  "annotation": "Anotar",
+  "monitor": "Monitor",
+  "monitor.advanced": "Avançado",
+  "monitor.advanced.tip": "Parâmetros de Configuração Avançada",
+  "monitor.app": "Tipo de Monitor",
+  "monitor.app.api": "API HTTP",
+  "monitor.app.fullsite": "Monitor de Mapa do Site",
+  "monitor.app.http": "API HTTP",
+  "monitor.app.mysql": "Mysql",
+  "monitor.app.oracle": "Oracle",
+  "monitor.app.ping": "Conexão PING",
+  "monitor.app.port": "Porta Disponível",
+  "monitor.app.redis": "Redis",
+  "monitor.app.website": "Monitor de Site",
+  "monitor.availability": "Disponibilidade do Monitor",
+  "monitor.cancel": "Pausar Monitor",
+  "monitor.category": "Categoria",
+  "monitor.category.auto": "Tarefa Automática",
+  "monitor.category.bigdata": "Big Data",
+  "monitor.category.cache": "Cache",
+  "monitor.category.cn": "Nativo da Nuvem",
+  "monitor.category.custom": "Personalizado",
+  "monitor.category.db": "Banco de Dados",
+  "monitor.category.mid": "Middleware",
+  "monitor.category.network": "Rede",
+  "monitor.category.os": "Sistema Operacional",
+  "monitor.category.program": "Aplicação",
+  "monitor.category.server": "Monitor de Servidor",
+  "monitor.category.service": "Serviço",
+  "monitor.category.webserver": "Servidor Web",
+  "monitor.export-all": "Exportar Todos",
+  "monitor.export-all.use-type": "Exportar todos os monitores no formato {{type}}",
+  "monitor.help": "Página de monitoramento e gerenciamento, você pode verificar os dados das métricas e gerenciar tarefas de monitoramento aqui. O status do serviço normal é",
+  "monitor.item.unavailable": "Este item de monitor não está mais disponível, possivelmente devido ao serviço estar offline. Retornando à página da lista...",
+  "monitor.item.unavailable.refresh": "Este item de monitor não está mais disponível, a lista será atualizada automaticamente",
+  "monitor.status.unavailable": "Indisponível",
+  "monitor.favorite.add.success": "Adicionado aos favoritos com sucesso",
+  "monitor.favorite.add.failed": "Falha ao adicionar aos favoritos",
+  "monitor.favorite.remove.success": "Removido dos favoritos com sucesso",
+  "monitor.favorite.remove.failed": "Falha ao remover dos favoritos",
+  "monitor.detail.favorite": "Favoritos",
+  "monitor.favorite.empty": "Ainda não há métricas favoritas",
+  "monitor.favorite.empty.realtime": "Ainda não há métricas em tempo real favoritas",
+  "monitor.favorite.empty.history": "Ainda não há gráficos históricos favoritos",
+  "monitor.favorite.add": "Adicionar aos Favoritos",
+  "monitor.favorite.remove": "Remover dos Favoritos",
+  "placeholder.key": "Chave",
+  "placeholder.value": "Valor",
+  "question.link": "https://hertzbeat.apache.org/docs/help/issue/",
+  "settings.system-config.locale.ja-JP": "Japonês(ja_JP)",
+  "about.not-show-next-login": "Não mostrar este popup no próximo login",
+  "alert.center.end-time": "Hora de Término",
+  "alert.center.labels": "Etiquetas",
+  "alert.group-converge.delete": "Excluir Estratégia de Convergência",
+  "alert.group-converge.edit": "Editar Estratégia de Convergência",
+  "alert.help.inhibit.link": "https://hertzbeat.apache.org/docs/help/alert_inhibit",
+  "alert.help.integration.link": "https://hertzbeat.apache.org",
+  "alert.notice.sender.sms.alibaba.accessKeyId": "Alibaba SMS AccessKeyId",
+  "alert.notice.sender.sms.alibaba.accessKeySecret": "Alibaba SMS AccessKeySecret",
+  "alert.notice.sender.sms.alibaba.signName": "Nome da Assinatura Alibaba SMS",
+  "alert.notice.sender.sms.alibaba.templateCode": "Código do Template Alibaba SMS",
+  "alert.notice.sender.sms.unisms.accessKeyId": "UniSMS AccessKeyId",
+  "alert.notice.sender.sms.unisms.accessKeySecret": "UniSMS AccessKeySecret",
+  "alert.notice.sender.sms.unisms.signature": "Assinatura UniSMS",
+  "alert.notice.sender.sms.unisms.templateId": "UniSMS TemplateId",
+  "alert.notice.sender.sms.unisms.authMode": "Modo de Autenticação UniSMS",
+  "alert.notice.sender.sms.smslocal.apiKey": "Smslocal ApiKey",
+  "alert.notice.sender.sms.aws.accessKeyId": "Aws SMS AccessKeyId",
+  "alert.notice.sender.sms.aws.accessKeySecret": "Aws SMS AccessKeySecret",
+  "alert.notice.sender.sms.aws.region": "Região Aws",
+  "alert.notice.sender.sms.twilio.accountSid": "Twilio Account SID",
+  "alert.notice.sender.sms.twilio.authToken": "Twilio Auth Token",
+  "alert.notice.sender.sms.twilio.twilioPhoneNumber": "Número de Telefone Twilio",
+  "alert.notice.sender.sms.type.unisms": "UniSMS",
+  "alert.notice.sender.sms.type.smslocal": "Smslocal Sms",
+  "alert.notice.sender.sms.type.aws": "Aws Sms",
+  "alert.notice.sender.sms.type.twilio": "Twilio Sms",
+  "alert.notice.type.telegram": "Telegram",
+  "alert.setting.expr.operator.and": "E",
+  "alert.setting.expr.operator.brackets": "Parênteses",
+  "alert.setting.expr.operator.equals": "Igual",
+  "alert.setting.expr.operator.greater": "Maior Que",
+  "alert.setting.expr.operator.greater-equals": "Maior ou Igual",
+  "alert.setting.expr.operator.less": "Menor Que",
+  "alert.setting.expr.operator.less-equals": "Menor ou Igual",
+  "alert.setting.expr.operator.not-equals": "Não Igual",
+  "alert.setting.expr.operator.or": "Ou",
+  "alert.setting.period.tip": "Intervalo de tempo para cálculo periódico de limite, em segundos, mínimo 60 segundos",
+  "alert.setting.preview.expr": "Visualizar Expressão",
+  "alert.setting.promql.tip": "Consulta PromQL: sum(rate(process_cpu_seconds_total[5m])) > 0.8",
+  "alert.setting.template.vars.labels": "Etiquetas",
+  "alert.silence.labels": "Correspondência de Etiqueta",
+  "annotation.bind": "Vincular Anotações",
+  "annotation.bind.tip": "Você pode usar anotações para marcar informações de entidade, como anotar eventos importantes para vinculação de recursos.",
+  "bulletin.batch.delete": "Excluir em Lote",
+  "bulletin.delete": "Excluir Boletim",
+  "bulletin.edit": "Editar Boletim",
+  "bulletin.help.content": "Conteúdo de Ajuda do Boletim",
+  "bulletin.help.link": "https://hertzbeat.apache.org/docs/help/bulletin",
+  "bulletin.monitor.metrics": "Métricas do Monitor",
+  "bulletin.monitor.name": "Nome do Monitor",
+  "bulletin.monitor.type": "Tipo de Monitor",
+  "bulletin.name": "Nome do Boletim",
+  "bulletin.name.placeholder": "Digite o nome do boletim",
+  "bulletin.new": "Novo Boletim",
+  "common.notify.copy-fail": "Falha ao Copiar",
+  "common.notify.import-fail-detail": "Falha na Importação: Detalhes",
+  "common.notify.import-success-detail": "Importação Bem-sucedida: Detalhes",
+  "common.notify.import-submitted": "Importação Enviada",
+  "common.notify.import-progress": "Progresso da Importação",
+  "common.notify.query-fail": "Falha na Consulta",
+  "define.disable": "Desabilitar",
+  "define.enable": "Habilitar"
 }
diff --git a/web-app/src/assets/i18n/zh-CN.json b/web-app/src/assets/i18n/zh-CN.json
index aea4f10c93..9595834d16 100644
--- a/web-app/src/assets/i18n/zh-CN.json
+++ b/web-app/src/assets/i18n/zh-CN.json
@@ -695,6 +695,7 @@
   "menu.advanced.labels": "标签管理",
   "menu.advanced.plugins": "插件管理",
   "menu.advanced.status": "状态页面",
+  "menu.advanced.mcp-server": "MCP服务器",
   "menu.alert": "告警",
   "menu.alert.center": "告警中心",
   "menu.alert.converge": "收敛",
@@ -712,7 +713,7 @@
   "menu.dashboard": "仪表盘",
   "menu.extras": "更多",
   "menu.extras.about": "关于",
-  "menu.extras.ai.chat": "AI智能助手",
+  "menu.extras.ai.chat": "HertzBeat AI",
   "menu.extras.help": "帮助中心",
   "menu.extras.setting": "设置",
   "menu.extras.settings": "系统设置",
@@ -843,6 +844,7 @@
   "monitor.holdingRegisterAddresses.tip": "输入寄存器地址",
   "monitor.host": "目标Host",
   "monitor.host.tip": "被监控的对端IP或域名",
+  "monitor.help": "监控管理页面,您可以在此查看指标数据并管理监控任务。正常服务的状态为",
   "monitor.icon.bigdata": "dot-chart",
   "monitor.icon.cache": "group",
   "monitor.icon.center": "laptop",
@@ -1064,5 +1066,60 @@
   "ai.bot.input.placeholder": "请输入问题...",
   "ai.bot.send": "发送",
   "ai.bot.connect-fail": "抱歉,连接AI助手时出现问题,请稍后再试。",
-  "monitor.help": "监控管理页面,您可以在此查看指标数据并管理监控任务。正常服务的状态为"
+  "ai.chat.assistant": "AI 助手",
+  "ai.chat.config.api-key": "API 密钥",
+  "ai.chat.config.api-key.help": "您的提供商 API 密钥。保存时将验证密钥。",
+  "ai.chat.config.api-key.required": "API 密钥是必需的",
+  "ai.chat.config.base-url": "基础 URL",
+  "ai.chat.config.base-url.help": "自定义 API 端点 URL。留空则使用所选提供商的默认值。",
+  "ai.chat.config.cancel": "取消",
+  "ai.chat.config.model": "模型",
+  "ai.chat.config.model.help": "要使用的模型名称。留空则使用所选提供商的默认值。",
+  "ai.chat.config.provider": "AI 提供商",
+  "ai.chat.config.provider.help": "选择您的 AI 提供商(OpenAI、智谱或 ZAI)",
+  "ai.chat.config.provider.required": "请选择 AI 提供商",
+  "ai.chat.config.reset": "重置为默认值",
+  "ai.chat.config.save": "保存",
+  "ai.chat.config.title": "AI 提供商配置",
+  "ai.chat.input.hint": "按 Enter 发送,Shift+Enter 换行",
+  "ai.chat.input.placeholder": "询问任何关于可观测的问题...",
+  "ai.chat.loading": "正在加载对话历史...",
+  "ai.chat.modify-api-key": "修改 API 密钥",
+  "ai.chat.new-chat": "新建对话",
+  "ai.chat.thinking": "AI 正在思考...",
+  "ai.chat.title": "HertzBeat AI",
+  "ai.chat.typing": "正在输入...",
+  "ai.chat.user": "您",
+  "ai.chat.welcome.capabilities.alerts": "查看和分析具有全面过滤功能的告警",
+  "ai.chat.welcome.capabilities.config": "配置告警规则和阈值",
+  "ai.chat.welcome.capabilities.manage": "按状态、类型或标签查询和管理监控器",
+  "ai.chat.welcome.capabilities.metrics": "访问实时和历史指标数据",
+  "ai.chat.welcome.capabilities.monitor": "为网站、API、数据库和服务添加新的监控器",
+  "ai.chat.welcome.capabilities.troubleshoot": "排查整个基础设施的性能问题",
+  "ai.chat.welcome.description": "我是您的智能可观测伙伴,随时准备帮助您管理和优化基础设施可观测。您可以要求我:",
+  "ai.chat.welcome.title": "欢迎使用 HertzBeat AI!",
+  "ai.chat.conversation.created": "新对话已创建",
+  "ai.chat.conversation.delete.title": "删除对话",
+  "ai.chat.conversation.delete.content": "您确定要删除这个对话吗?",
+  "ai.chat.conversation.delete.confirm": "删除",
+  "ai.chat.conversation.delete.success": "对话已删除",
+  "ai.chat.conversation.delete.failed": "删除对话失败",
+  "ai.chat.config.required.title": "需要 AI 模型提供商配置",
+  "ai.chat.config.required.content": "要使用 AI 智能体聊天,请配置您的模型提供商。",
+  "ai.chat.config.required.error": "配置问题:",
+  "ai.chat.config.required.button": "在此配置",
+  "ai.chat.config.validation.failed": "❌ API 密钥验证失败:",
+  "ai.chat.config.save.success": "模型提供商配置保存成功!",
+  "ai.chat.config.save.failed": "保存配置失败:",
+  "ai.chat.error.api.key": "请输入 API 密钥",
+  "ai.chat.error.provider": "请选择提供商",
+  "ai.chat.error.base.url": "请输入基础 URL",
+  "ai.chat.error.model": "请输入模型",
+  "ai.chat.error.conversations.load": "加载对话失败:",
+  "ai.chat.error.conversation.create": "创建新对话失败:",
+  "ai.chat.error.conversation.history": "加载对话历史失败",
+  "ai.chat.error.chat.response": "获取 AI 回复失败:",
+  "ai.chat.error.processing": "处理您的请求时出错。请检查 AI 智能体服务是否正在运行,然后重试。",
+  "ai.chat.offline.mode": "AI 聊天服务不可用。正在离线模式下运行。",
+  "ai.chat.offline.response": "抱歉,AI 聊天服务当前不可用。请确保 HertzBeat AI 模块正在运行,稍后再试。"
 }
diff --git a/web-app/src/assets/i18n/zh-TW.json b/web-app/src/assets/i18n/zh-TW.json
index 9a716351c5..23222ea884 100644
--- a/web-app/src/assets/i18n/zh-TW.json
+++ b/web-app/src/assets/i18n/zh-TW.json
@@ -687,6 +687,7 @@
   "menu.advanced.labels": "標簽管理",
   "menu.advanced.plugins": "外掛管理",
   "menu.advanced.status": "狀態頁面",
+  "menu.advanced.mcp-server": "MCP伺服器",
   "menu.alert": "告警",
   "menu.alert.center": "告警中心",
   "menu.alert.converge": "告警收斂",
@@ -700,7 +701,7 @@
   "menu.dashboard": "儀表盤",
   "menu.extras": "更多",
   "menu.extras.about": "關於",
-  "menu.extras.ai.chat": "AI智能助手",
+  "menu.extras.ai.chat": "HertzBeat AI",
   "menu.extras.help": "幫助中心",
   "menu.extras.setting": "設置",
   "menu.extras.settings": "系統設置",
@@ -1050,5 +1051,61 @@
   "ai.bot.greeting": "你好!我是AI助手,有什麽可以幫助你的嗎?",
   "ai.bot.input.placeholder": "請輸入問題...",
   "ai.bot.send": "傳送",
-  "ai.bot.connect-fail": "抱歉,連線至AI助手時出現問題,請稍後再試。"
+  "ai.bot.connect-fail": "抱歉,連線至AI助手時出現問題,請稍後再試。",
+  "ai.chat.assistant": "AI 助手",
+  "ai.chat.config.api-key": "API 金鑰",
+  "ai.chat.config.api-key.help": "您的提供商 API 金鑰。儲存時將驗證金鑰。",
+  "ai.chat.config.api-key.required": "API 金鑰是必需的",
+  "ai.chat.config.base-url": "基礎 URL",
+  "ai.chat.config.base-url.help": "自訂 API 端點 URL。留空則使用所選提供商的預設值。",
+  "ai.chat.config.cancel": "取消",
+  "ai.chat.config.model": "模型",
+  "ai.chat.config.model.help": "要使用的模型名稱。留空則使用所選提供商的預設值。",
+  "ai.chat.config.provider": "AI 提供商",
+  "ai.chat.config.provider.help": "選擇您的 AI 提供商(OpenAI、智譜或 ZAI)",
+  "ai.chat.config.provider.required": "請選擇 AI 提供商",
+  "ai.chat.config.reset": "重設為預設值",
+  "ai.chat.config.save": "儲存",
+  "ai.chat.config.title": "AI 提供商配置",
+  "ai.chat.input.hint": "按 Enter 傳送,Shift+Enter 換行",
+  "ai.chat.input.placeholder": "詢問任何關於可觀測的問題...",
+  "ai.chat.loading": "正在載入對話歷史...",
+  "ai.chat.modify-api-key": "修改 API 金鑰",
+  "ai.chat.new-chat": "新建對話",
+  "ai.chat.thinking": "AI 正在思考...",
+  "ai.chat.title": "HertzBeat AI",
+  "ai.chat.typing": "正在輸入...",
+  "ai.chat.user": "您",
+  "ai.chat.welcome.capabilities.alerts": "檢視和分析具有全面過濾功能的告警",
+  "ai.chat.welcome.capabilities.config": "配置告警規則和閾值",
+  "ai.chat.welcome.capabilities.manage": "按狀態、類型或標籤查詢和管理監控器",
+  "ai.chat.welcome.capabilities.metrics": "存取即時和歷史指標資料",
+  "ai.chat.welcome.capabilities.monitor": "為網站、API、資料庫和服務新增新的監控器",
+  "ai.chat.welcome.capabilities.troubleshoot": "排查整個基礎設施的效能問題",
+  "ai.chat.welcome.description": "我是您的智慧可觀測夥伴,隨時準備幫助您管理和最佳化基礎設施可觀測。您可以要求我:",
+  "ai.chat.welcome.title": "歡迎使用 HertzBeat AI!",
+  "ai.chat.conversation.created": "新對話已建立",
+  "ai.chat.conversation.delete.title": "刪除對話",
+  "ai.chat.conversation.delete.content": "您確定要刪除這個對話嗎?",
+  "ai.chat.conversation.delete.confirm": "刪除",
+  "ai.chat.conversation.delete.success": "對話已刪除",
+  "ai.chat.conversation.delete.failed": "刪除對話失敗",
+  "ai.chat.config.required.title": "需要 AI 模型提供商配置",
+  "ai.chat.config.required.content": "要使用 AI 智能體聊天,請配置您的模型提供商。",
+  "ai.chat.config.required.error": "配置問題:",
+  "ai.chat.config.required.button": "在此配置",
+  "ai.chat.config.validation.failed": "❌ API 金鑰驗證失敗:",
+  "ai.chat.config.save.success": "模型提供商配置儲存成功!",
+  "ai.chat.config.save.failed": "儲存配置失敗:",
+  "ai.chat.error.api.key": "請輸入 API 金鑰",
+  "ai.chat.error.provider": "請選擇提供商",
+  "ai.chat.error.base.url": "請輸入基礎 URL",
+  "ai.chat.error.model": "請輸入模型",
+  "ai.chat.error.conversations.load": "載入對話失敗:",
+  "ai.chat.error.conversation.create": "建立新對話失敗:",
+  "ai.chat.error.conversation.history": "載入對話歷史失敗",
+  "ai.chat.error.chat.response": "取得 AI 回覆失敗:",
+  "ai.chat.error.processing": "處理您的請求時發生錯誤。請檢查 AI 智能體服務是否正在執行,然後重試。",
+  "ai.chat.offline.mode": "AI 聊天服務不可用。正在離線模式下執行。",
+  "ai.chat.offline.response": "抱歉,AI 聊天服務目前不可用。請確保 HertzBeat AI 模組正在執行,稍後再試。"
 }
diff --git a/web-app/src/styles/index.less b/web-app/src/styles/index.less
index 042f073806..23c13d43fb 100644
--- a/web-app/src/styles/index.less
+++ b/web-app/src/styles/index.less
@@ -24,7 +24,7 @@ html {
 
 /* Enhanced card styling */
 .ant-card {
-  border-radius: 12px !important;
+  border-radius: 8px !important;
   box-shadow: 0 4px 16px rgba(0, 0, 0, 0.04) !important;
   border: 1px solid rgba(0, 0, 0, 0.06) !important;
   transition: all 0.3s ease !important;
@@ -51,7 +51,7 @@ html {
 
 /* Enhanced table styling */
 .ant-table {
-  border-radius: 12px !important;
+  border-radius: 8px !important;
   overflow: hidden !important;
 }
 
@@ -67,7 +67,7 @@ html {
 
 /* Enhanced modal styling */
 .ant-modal-content {
-  border-radius: 16px !important;
+  border-radius: 8px !important;
   box-shadow: 0 16px 48px rgba(0, 0, 0, 0.12) !important;
 }
 
diff --git a/web-app/src/styles/theme.less b/web-app/src/styles/theme.less
index a499b1690d..46f0c9da57 100644
--- a/web-app/src/styles/theme.less
+++ b/web-app/src/styles/theme.less
@@ -49,7 +49,7 @@
 }
 
 .br-8, .ant-modal-header, .ant-modal-content {
-  border-radius: 8px;
+  border-radius: 6px;
 }
 
 // bugfix https://github.com/apache/hertzbeat/issues/133
@@ -114,4 +114,4 @@
 .alain-default__header-logo-expanded, .alain-default__header-logo-collapsed {
   max-width: 90%;
   max-height: 46px;
-}
\ No newline at end of file
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@hertzbeat.apache.org
For additional commands, e-mail: notifications-help@hertzbeat.apache.org