feat: 监控告警体系统一重构 + 自动化任务调度引擎 + 监控大屏拆分
告警中心 - 新增统一告警(alert_unified)、监控告警规则(monitor_alert_rule)、指标目录(alert_metric_catalog) - 通知策略与消息分发(alert_notify_policy/dispatch/message)、静默规则 - 告警引擎按阈值/SNMP 拆分(alert_engine_monitor/snmp) 监控采集 - SNMP 常量/模板与历史指标(snmp templates/constants、snmp_metrics_history、snmp_collect) - 中间件监控 Redis 采集与种子(middleware_monitor_redis/seed) - 站点探测 pkg(siteprobe) + 站点视图(site_view) 自动化任务 - cron 调度器(cronscheduler)、脚本运行器(scriptrunner)、系统任务(systask)及运行记录(cron_job_run、system_task) 审计与凭证 - 审计设置(audit_setting) + 历史清理(auditcleaner) 前端 - 监控页面(host/middleware/site/snmp)拆分为子模块并大屏化 - 告警中心多 Tab(规则/指标目录/通知策略/静默)、任务管理组件重构、Agent CLI Markdown 渲染 - 移除旧脚本卡片/详情/日志组件,统一为 ScriptTable/ScriptCodeEditor/TerminalOutput Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
092d0e4b9e
commit
471353e3d7
190 files changed
+16640
-3484
No files matched your search
@@ -54,8 +54,9 @@ type wsEvent struct {
|
||||
|
||||
// wsControl 前端→后端控制消息 // Logan.Li
|
||||
type wsControl struct {
|
||||
Type string `json:"type"` // start/continue/confirm/deny/abort
|
||||
Query string `json:"query,omitempty"` // start 时任务描述
|
||||
Type string `json:"type"` // start/continue/resume/confirm/deny/abort
|
||||
Query string `json:"query,omitempty"` // start/continue 时任务描述
|
||||
SessionID uint `json:"session_id,omitempty"` // resume 时恢复的历史会话 ID
|
||||
SafetyMode string `json:"safety_mode,omitempty"` // strict/balanced/permissive
|
||||
ConfirmID string `json:"confirm_id,omitempty"` // confirm/deny 时
|
||||
}
|
||||
@@ -159,6 +160,12 @@ func (h *AgentCLIHandler) Run(c *gin.Context) {
|
||||
continue
|
||||
}
|
||||
ac.continueTask(sshCfg, ctrl.Query, ctrl.SafetyMode)
|
||||
case "resume":
|
||||
if ctrl.SessionID == 0 {
|
||||
ac.write(wsEvent{Type: "error", Message: "缺少 session_id"})
|
||||
continue
|
||||
}
|
||||
ac.resumeSession(ctrl.SessionID)
|
||||
case "confirm":
|
||||
ac.resolveConfirm(ctrl.ConfirmID, true)
|
||||
case "deny":
|
||||
@@ -211,6 +218,33 @@ func (ac *agentConn) startTask(sshCfg remoteexec.SSHConfig, query, safetyMode st
|
||||
ac.runTask(sshCfg, sess, query, safetyMode, llmCfg, false)
|
||||
}
|
||||
|
||||
// resumeSession 从历史会话恢复上下文,供继续追问 // Logan.Li
|
||||
func (ac *agentConn) resumeSession(sessionID uint) {
|
||||
if ac.isRunning() {
|
||||
ac.write(wsEvent{Type: "error", Message: "任务进行中,请等待完成或停止"})
|
||||
return
|
||||
}
|
||||
var sess model.AgentCLISession
|
||||
if err := ac.db.Where("user_id = ? AND server_id = ?", ac.userID, ac.server.ID).
|
||||
First(&sess, sessionID).Error; err != nil {
|
||||
ac.write(wsEvent{Type: "error", Message: "会话不存在或无权访问"})
|
||||
return
|
||||
}
|
||||
if sess.Status == "running" {
|
||||
ac.write(wsEvent{Type: "error", Message: "该会话仍在执行中,无法恢复"})
|
||||
return
|
||||
}
|
||||
var msgs []model.AgentCLIMessage
|
||||
ac.db.Where("session_id = ?", sessionID).Order("id ASC").Find(&msgs)
|
||||
ac.session = &sess
|
||||
ac.convHistory = buildConvHistoryFromMessages(msgs)
|
||||
ac.setTotalTokens(sess.TotalTokens)
|
||||
ac.write(wsEvent{
|
||||
Type: "session", SessionID: sess.ID,
|
||||
Message: fmt.Sprintf("已恢复历史会话「%s」,可继续追问或执行新指令", sess.Title),
|
||||
})
|
||||
}
|
||||
|
||||
// continueTask 在同一会话内追问(保留上下文) // Logan.Li
|
||||
func (ac *agentConn) continueTask(sshCfg remoteexec.SSHConfig, query, safetyMode string) {
|
||||
if ac.isRunning() {
|
||||
@@ -262,6 +296,7 @@ func (ac *agentConn) runTask(sshCfg remoteexec.SSHConfig, sess *model.AgentCLISe
|
||||
Core: coreCfg,
|
||||
})
|
||||
if err != nil {
|
||||
ac.write(wsEvent{Type: "error", Message: "引擎初始化失败: " + err.Error()})
|
||||
ac.finish(sess, "error", "引擎初始化失败: "+err.Error(), ac.lastRound(), 0)
|
||||
return
|
||||
}
|
||||
@@ -444,7 +479,8 @@ func (ac *agentConn) lastRound() int {
|
||||
func (ac *agentConn) finish(sess *model.AgentCLISession, status, errMsg string, rounds int, dur time.Duration) {
|
||||
ac.setRunning(false)
|
||||
tokens := ac.getTotalTokens()
|
||||
if status == "done" || status == "aborted" || status == "error" {
|
||||
// done/error 已由引擎 onEvent 推送;此处仅 aborted 需补推 WS(引擎初始化失败在 runTask 内单独推送) // Logan.Li
|
||||
if status == "aborted" {
|
||||
ac.write(wsEvent{Type: status, SessionID: sess.ID, Message: errMsg, Round: rounds, Tokens: tokens})
|
||||
}
|
||||
updates := map[string]interface{}{
|
||||
|
||||
Reference in new issue
Block a user