mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-19 01:17:16 +02:00
Add files via upload
This commit is contained in:
@@ -185,8 +185,9 @@ type AgentHandler struct {
|
|||||||
agentsMarkdownDir string // 多代理:Markdown 子 Agent 目录(绝对路径,空则不从磁盘合并)
|
agentsMarkdownDir string // 多代理:Markdown 子 Agent 目录(绝对路径,空则不从磁盘合并)
|
||||||
batchCronParser cron.Parser
|
batchCronParser cron.Parser
|
||||||
// hitlWhitelistSaver 侧栏「应用」HITL 时将会话增量白名单合并写入 config.yaml(可选)
|
// hitlWhitelistSaver 侧栏「应用」HITL 时将会话增量白名单合并写入 config.yaml(可选)
|
||||||
hitlWhitelistSaver HitlToolWhitelistSaver
|
hitlWhitelistSaver HitlToolWhitelistSaver
|
||||||
hitlStrategySaver HitlAuditStrategySaver
|
hitlStrategySaver HitlAuditStrategySaver
|
||||||
|
hitlDefaultReviewerSaver HitlDefaultReviewerSaver
|
||||||
auditLLM *openai.Client
|
auditLLM *openai.Client
|
||||||
audit *audit.Service
|
audit *audit.Service
|
||||||
}
|
}
|
||||||
@@ -288,6 +289,23 @@ func (h *AgentHandler) SetHitlToolWhitelistSaver(s HitlToolWhitelistSaver) {
|
|||||||
h.hitlWhitelistSaver = s
|
h.hitlWhitelistSaver = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HitlDefaultReviewerSaver 持久化全局默认审批方到 config.yaml。
|
||||||
|
type HitlDefaultReviewerSaver interface {
|
||||||
|
UpdateHitlDefaultReviewer(reviewer string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHitlDefaultReviewerSaver 设置 HITL 默认审批方落盘。
|
||||||
|
func (h *AgentHandler) SetHitlDefaultReviewerSaver(s HitlDefaultReviewerSaver) {
|
||||||
|
h.hitlDefaultReviewerSaver = s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *AgentHandler) hitlEffectiveDefaultReviewer() string {
|
||||||
|
if h != nil && h.config != nil {
|
||||||
|
return normalizeHitlReviewer(h.config.Hitl.EffectiveDefaultReviewer())
|
||||||
|
}
|
||||||
|
return "human"
|
||||||
|
}
|
||||||
|
|
||||||
// HITLNeedsToolApproval 供 C2 危险任务门控:与会话侧人机协同及免审批白名单判定一致。
|
// HITLNeedsToolApproval 供 C2 危险任务门控:与会话侧人机协同及免审批白名单判定一致。
|
||||||
func (h *AgentHandler) HITLNeedsToolApproval(conversationID, toolName string) bool {
|
func (h *AgentHandler) HITLNeedsToolApproval(conversationID, toolName string) bool {
|
||||||
if h == nil || h.hitlManager == nil {
|
if h == nil || h.hitlManager == nil {
|
||||||
|
|||||||
@@ -1802,10 +1802,23 @@ func updateHitlConfig(doc *yaml.Node, cfg config.HitlConfig) {
|
|||||||
hitlNode := ensureMap(root, "hitl")
|
hitlNode := ensureMap(root, "hitl")
|
||||||
// flow 样式 [a, b, c] 单行展示,工具多时比块序列省行数
|
// flow 样式 [a, b, c] 单行展示,工具多时比块序列省行数
|
||||||
setFlowStringSliceInMap(hitlNode, "tool_whitelist", cfg.ToolWhitelist)
|
setFlowStringSliceInMap(hitlNode, "tool_whitelist", cfg.ToolWhitelist)
|
||||||
|
setStringInMap(hitlNode, "default_reviewer", cfg.EffectiveDefaultReviewer())
|
||||||
setStringInMap(hitlNode, "audit_agent_prompt", cfg.AuditAgentPrompt)
|
setStringInMap(hitlNode, "audit_agent_prompt", cfg.AuditAgentPrompt)
|
||||||
setStringInMap(hitlNode, "audit_agent_prompt_review_edit", cfg.AuditAgentPromptReviewEdit)
|
setStringInMap(hitlNode, "audit_agent_prompt_review_edit", cfg.AuditAgentPromptReviewEdit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateHitlDefaultReviewer 更新全局默认审批方并写入 config.yaml。
|
||||||
|
func (h *ConfigHandler) UpdateHitlDefaultReviewer(reviewer string) error {
|
||||||
|
h.mu.Lock()
|
||||||
|
defer h.mu.Unlock()
|
||||||
|
h.config.Hitl.DefaultReviewer = config.HitlConfig{DefaultReviewer: reviewer}.EffectiveDefaultReviewer()
|
||||||
|
if err := h.saveConfig(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h.logger.Info("HITL 全局默认审批方已写入配置文件", zap.String("default_reviewer", h.config.Hitl.DefaultReviewer))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateHitlAuditAgentStrategy 更新审批/审查编辑两套审计 Agent 提示词并写入 config.yaml。
|
// UpdateHitlAuditAgentStrategy 更新审批/审查编辑两套审计 Agent 提示词并写入 config.yaml。
|
||||||
func (h *ConfigHandler) UpdateHitlAuditAgentStrategy(approvalPrompt, reviewEditPrompt string) error {
|
func (h *ConfigHandler) UpdateHitlAuditAgentStrategy(approvalPrompt, reviewEditPrompt string) error {
|
||||||
h.mu.Lock()
|
h.mu.Lock()
|
||||||
|
|||||||
@@ -389,6 +389,18 @@ func (m *HITLManager) LoadConversationConfig(conversationID string) (*HITLReques
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *HITLManager) HasConversationConfig(conversationID string) (bool, error) {
|
||||||
|
if strings.TrimSpace(conversationID) == "" {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
var one int
|
||||||
|
err := m.db.QueryRow(`SELECT 1 FROM hitl_conversation_configs WHERE conversation_id = ? LIMIT 1`, conversationID).Scan(&one)
|
||||||
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return err == nil, err
|
||||||
|
}
|
||||||
|
|
||||||
func (m *HITLManager) waitDecision(ctx context.Context, p *pendingInterrupt, timeout time.Duration) (hitlDecision, error) {
|
func (m *HITLManager) waitDecision(ctx context.Context, p *pendingInterrupt, timeout time.Duration) (hitlDecision, error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
@@ -427,14 +439,32 @@ func (h *AgentHandler) activateHITLForConversation(conversationID string, req *H
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req == nil {
|
if req == nil {
|
||||||
cfg, err := h.hitlManager.LoadConversationConfig(conversationID)
|
cfg, err := h.loadHITLConversationConfig(conversationID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
req = cfg
|
req = cfg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if req != nil && strings.TrimSpace(req.Reviewer) == "" {
|
||||||
|
req.Reviewer = h.hitlEffectiveDefaultReviewer()
|
||||||
|
}
|
||||||
h.hitlManager.ActivateConversation(conversationID, h.hitlRequestWithMergedConfigWhitelist(req))
|
h.hitlManager.ActivateConversation(conversationID, h.hitlRequestWithMergedConfigWhitelist(req))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *AgentHandler) loadHITLConversationConfig(conversationID string) (*HITLRequest, error) {
|
||||||
|
cfg, err := h.hitlManager.LoadConversationConfig(conversationID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
has, err := h.hitlManager.HasConversationConfig(conversationID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
cfg.Reviewer = h.hitlEffectiveDefaultReviewer()
|
||||||
|
}
|
||||||
|
return cfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (h *AgentHandler) waitHITLApproval(runCtx context.Context, cancelRun context.CancelCauseFunc, conversationID, assistantMessageID, toolName, toolCallID string, payload map[string]interface{}, sendEventFunc func(eventType, message string, data interface{})) (*hitlDecision, error) {
|
func (h *AgentHandler) waitHITLApproval(runCtx context.Context, cancelRun context.CancelCauseFunc, conversationID, assistantMessageID, toolName, toolCallID string, payload map[string]interface{}, sendEventFunc func(eventType, message string, data interface{})) (*hitlDecision, error) {
|
||||||
cfg, need := h.hitlManager.shouldInterrupt(conversationID, toolName)
|
cfg, need := h.hitlManager.shouldInterrupt(conversationID, toolName)
|
||||||
if !need {
|
if !need {
|
||||||
@@ -710,7 +740,7 @@ func (h *AgentHandler) GetHITLConversationConfig(c *gin.Context) {
|
|||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "conversationId is required"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "conversationId is required"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cfg, err := h.hitlManager.LoadConversationConfig(conversationID)
|
cfg, err := h.loadHITLConversationConfig(conversationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
@@ -729,6 +759,7 @@ func (h *AgentHandler) GetHITLConversationConfig(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"conversationId": conversationID,
|
"conversationId": conversationID,
|
||||||
"hitl": cfg,
|
"hitl": cfg,
|
||||||
|
"defaultReviewer": h.hitlEffectiveDefaultReviewer(),
|
||||||
"hitlGlobalToolWhitelist": h.hitlConfigGlobalToolWhitelist(),
|
"hitlGlobalToolWhitelist": h.hitlConfigGlobalToolWhitelist(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -741,6 +772,9 @@ func (h *AgentHandler) UpsertHITLConversationConfig(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
req.Mode = normalizeHitlMode(req.Mode)
|
req.Mode = normalizeHitlMode(req.Mode)
|
||||||
req.Reviewer = normalizeHitlReviewer(req.Reviewer)
|
req.Reviewer = normalizeHitlReviewer(req.Reviewer)
|
||||||
|
if strings.TrimSpace(req.Reviewer) == "" {
|
||||||
|
req.Reviewer = h.hitlEffectiveDefaultReviewer()
|
||||||
|
}
|
||||||
if err := h.hitlManager.SaveConversationConfig(req.ConversationID, &req.HITLRequest); err != nil {
|
if err := h.hitlManager.SaveConversationConfig(req.ConversationID, &req.HITLRequest); err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
@@ -769,7 +803,48 @@ type setHitlGlobalWhitelistReq struct {
|
|||||||
// GetHITLGlobalToolWhitelist 返回 config.yaml 中的全局免审批工具白名单。
|
// GetHITLGlobalToolWhitelist 返回 config.yaml 中的全局免审批工具白名单。
|
||||||
func (h *AgentHandler) GetHITLGlobalToolWhitelist(c *gin.Context) {
|
func (h *AgentHandler) GetHITLGlobalToolWhitelist(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"toolWhitelist": h.hitlConfigGlobalToolWhitelist(),
|
"toolWhitelist": h.hitlConfigGlobalToolWhitelist(),
|
||||||
|
"defaultReviewer": h.hitlEffectiveDefaultReviewer(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type setHitlDefaultReviewerReq struct {
|
||||||
|
Reviewer string `json:"reviewer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHITLDefaultReviewer 返回 config.yaml 中的全局默认审批方。
|
||||||
|
func (h *AgentHandler) GetHITLDefaultReviewer(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"defaultReviewer": h.hitlEffectiveDefaultReviewer(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateHITLDefaultReviewer 将全局默认审批方写入 config.yaml(未选会话时切换审批方)。
|
||||||
|
func (h *AgentHandler) UpdateHITLDefaultReviewer(c *gin.Context) {
|
||||||
|
if h.hitlDefaultReviewerSaver == nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "HITL 配置持久化不可用"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var req setHitlDefaultReviewerReq
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
reviewer := normalizeHitlReviewer(req.Reviewer)
|
||||||
|
if err := h.hitlDefaultReviewerSaver.UpdateHitlDefaultReviewer(reviewer); err != nil {
|
||||||
|
h.logger.Warn("写入 HITL 默认审批方到 config.yaml 失败", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if h.config != nil {
|
||||||
|
h.config.Hitl.DefaultReviewer = reviewer
|
||||||
|
}
|
||||||
|
if h.audit != nil {
|
||||||
|
h.audit.RecordOK(c, "hitl", "default_reviewer_update", "HITL 全局默认审批方更新", "hitl_config", "default_reviewer", nil)
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"ok": true,
|
||||||
|
"defaultReviewer": reviewer,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user