Add files via upload

This commit is contained in:
公明
2026-06-30 20:09:18 +08:00
committed by GitHub
parent e537e55198
commit 52de3b0f41
2 changed files with 70 additions and 2 deletions
+6
View File
@@ -21,6 +21,7 @@ import (
"cyberstrike-ai/internal/database"
"cyberstrike-ai/internal/einoobserve"
"cyberstrike-ai/internal/handler"
"cyberstrike-ai/internal/hitl"
"cyberstrike-ai/internal/knowledge"
"cyberstrike-ai/internal/logger"
"cyberstrike-ai/internal/mcp"
@@ -109,6 +110,10 @@ func New(cfg *config.Config, log *logger.Logger, configPath string) (*App, error
monitorRetention.PurgeExpired()
monitor.StartRetentionLoop(monitorRetention, log.Logger)
hitlRetention := hitl.NewService(db, cfg, log.Logger)
hitlRetention.PurgeExpired()
hitl.StartRetentionLoop(hitlRetention, log.Logger)
// 创建MCP服务器(带数据库持久化)
mcpServer := mcp.NewServerWithStorage(log.Logger, db)
mcpServer.ConfigureHTTPToolCallTimeoutFromAgentMinutes(cfg.Agent.ToolTimeoutMinutes)
@@ -814,6 +819,7 @@ func setupRoutes(
protected.POST("/eino-agent/stream", agentHandler.EinoSingleAgentLoopStream)
protected.GET("/hitl/pending", agentHandler.ListHITLPending)
protected.GET("/hitl/logs", agentHandler.ListHITLLogs)
protected.DELETE("/hitl/logs", agentHandler.DeleteHITLLogs)
protected.GET("/hitl/logs/:id", agentHandler.GetHITLLog)
protected.POST("/hitl/decision", agentHandler.DecideHITLInterrupt)
protected.POST("/hitl/dismiss", agentHandler.DismissHITLInterrupt)
+64 -2
View File
@@ -9,6 +9,8 @@ import (
"strings"
"time"
"cyberstrike-ai/internal/config"
"github.com/gin-gonic/gin"
)
@@ -73,7 +75,13 @@ func hitlInterruptRowToMap(
}
func (h *AgentHandler) buildHitlListQuery(logs bool) (string, []interface{}) {
q := `SELECT id, conversation_id, message_id, mode, tool_name, tool_call_id, payload, status, decision, decision_comment, COALESCE(decided_by,'human'), created_at, decided_at FROM hitl_interrupts WHERE 1=1`
where, args := h.buildHitlLogsWhere(logs)
q := `SELECT id, conversation_id, message_id, mode, tool_name, tool_call_id, payload, status, decision, decision_comment, COALESCE(decided_by,'human'), created_at, decided_at FROM hitl_interrupts` + where
return q, args
}
func (h *AgentHandler) buildHitlLogsWhere(logs bool) (string, []interface{}) {
q := " WHERE 1=1"
args := []interface{}{}
if logs {
q += " AND status != 'pending'"
@@ -173,7 +181,61 @@ func (h *AgentHandler) ListHITLLogs(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"items": items, "page": page, "pageSize": pageSize, "total": total})
c.JSON(http.StatusOK, gin.H{"items": items, "page": page, "pageSize": pageSize, "total": total, "retentionDays": h.hitlRetentionDays()})
}
func (h *AgentHandler) hitlRetentionDays() int {
if h.config != nil {
return h.config.Hitl.RetentionDaysEffective()
}
return config.HitlConfig{}.RetentionDaysEffective()
}
// DeleteHITLLogs 批量删除或按筛选清空已决策的人机协同审计日志(不删除 pending)。
func (h *AgentHandler) DeleteHITLLogs(c *gin.Context) {
var request struct {
IDs []string `json:"ids"`
All bool `json:"all"`
}
if err := c.ShouldBindJSON(&request); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数无效: " + err.Error()})
return
}
var deleted int64
var err error
if request.All {
where, args := h.buildHitlLogsWhere(true)
where, args = h.appendHitlListFilters(where, args, c)
deleted, err = h.db.DeleteHitlInterruptLogsMatching(where, args)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if h.audit != nil {
h.audit.RecordOK(c, "hitl", "logs_clear", "清空人机协同审计日志", "hitl_interrupt", "", map[string]interface{}{
"deleted": deleted,
})
}
} else {
if len(request.IDs) == 0 {
c.JSON(http.StatusBadRequest, gin.H{"error": "审计日志 ID 列表不能为空"})
return
}
deleted, err = h.db.DeleteHitlInterruptLogsByIDs(request.IDs)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if h.audit != nil {
h.audit.RecordOK(c, "hitl", "logs_delete_batch", "批量删除人机协同审计日志", "hitl_interrupt", "", map[string]interface{}{
"count": len(request.IDs),
"deleted": deleted,
})
}
}
c.JSON(http.StatusOK, gin.H{"message": "删除成功", "deleted": deleted})
}
func (h *AgentHandler) GetHITLLog(c *gin.Context) {