mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-07 19:38:41 +02:00
Add files via upload
This commit is contained in:
@@ -22,6 +22,7 @@ type Config struct {
|
|||||||
OpenAI OpenAIConfig `yaml:"openai"`
|
OpenAI OpenAIConfig `yaml:"openai"`
|
||||||
FOFA FofaConfig `yaml:"fofa,omitempty" json:"fofa,omitempty"`
|
FOFA FofaConfig `yaml:"fofa,omitempty" json:"fofa,omitempty"`
|
||||||
Agent AgentConfig `yaml:"agent"`
|
Agent AgentConfig `yaml:"agent"`
|
||||||
|
Hitl HitlConfig `yaml:"hitl,omitempty" json:"hitl,omitempty"`
|
||||||
Security SecurityConfig `yaml:"security"`
|
Security SecurityConfig `yaml:"security"`
|
||||||
Database DatabaseConfig `yaml:"database"`
|
Database DatabaseConfig `yaml:"database"`
|
||||||
Auth AuthConfig `yaml:"auth"`
|
Auth AuthConfig `yaml:"auth"`
|
||||||
@@ -244,6 +245,13 @@ type AgentConfig struct {
|
|||||||
SystemPromptPath string `yaml:"system_prompt_path,omitempty" json:"system_prompt_path,omitempty"`
|
SystemPromptPath string `yaml:"system_prompt_path,omitempty" json:"system_prompt_path,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HitlConfig 人机协同全局选项;与会话侧栏/API 中的白名单合并为并集后参与判定。
|
||||||
|
// tool_whitelist 可在侧栏「应用」时合并写入 config.yaml 并立即生效;其他字段若仅改文件仍需重启。
|
||||||
|
type HitlConfig struct {
|
||||||
|
// ToolWhitelist 全局免审批工具名(与每条会话配置的 sensitiveTools 语义相同:白名单内工具不触发 HITL)。
|
||||||
|
ToolWhitelist []string `yaml:"tool_whitelist,omitempty" json:"tool_whitelist,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
Password string `yaml:"password" json:"password"`
|
Password string `yaml:"password" json:"password"`
|
||||||
SessionDurationHours int `yaml:"session_duration_hours" json:"session_duration_hours"`
|
SessionDurationHours int `yaml:"session_duration_hours" json:"session_duration_hours"`
|
||||||
|
|||||||
@@ -230,6 +230,17 @@ attemptLoop:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.Err != nil {
|
if ev.Err != nil {
|
||||||
|
if errors.Is(ev.Err, context.DeadlineExceeded) {
|
||||||
|
flushAllPendingAsFailed(ev.Err)
|
||||||
|
if progress != nil {
|
||||||
|
progress("error", ev.Err.Error(), map[string]interface{}{
|
||||||
|
"conversationId": conversationID,
|
||||||
|
"source": "eino",
|
||||||
|
"errorKind": "timeout",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil, ev.Err
|
||||||
|
}
|
||||||
// context.Canceled 是唯一应当直接终止编排的错误(用户关闭页面、主动停止等)。
|
// context.Canceled 是唯一应当直接终止编排的错误(用户关闭页面、主动停止等)。
|
||||||
if errors.Is(ev.Err, context.Canceled) {
|
if errors.Is(ev.Err, context.Canceled) {
|
||||||
flushAllPendingAsFailed(ev.Err)
|
flushAllPendingAsFailed(ev.Err)
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ func RunEinoSingleChatModelAgent(
|
|||||||
Tools: mainToolsForCfg,
|
Tools: mainToolsForCfg,
|
||||||
UnknownToolsHandler: einomcp.UnknownToolReminderHandler(),
|
UnknownToolsHandler: einomcp.UnknownToolReminderHandler(),
|
||||||
ToolCallMiddlewares: []compose.ToolMiddleware{
|
ToolCallMiddlewares: []compose.ToolMiddleware{
|
||||||
|
{Invokable: hitlToolCallMiddleware()},
|
||||||
{Invokable: softRecoveryToolCallMiddleware()},
|
{Invokable: softRecoveryToolCallMiddleware()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package multiagent
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/cloudwego/eino/adk"
|
||||||
|
"github.com/cloudwego/eino/compose"
|
||||||
|
)
|
||||||
|
|
||||||
|
type hitlInterceptorKey struct{}
|
||||||
|
|
||||||
|
type HITLToolInterceptor func(ctx context.Context, toolName, arguments string) (string, error)
|
||||||
|
|
||||||
|
type humanRejectError struct {
|
||||||
|
reason string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *humanRejectError) Error() string {
|
||||||
|
if strings.TrimSpace(e.reason) == "" {
|
||||||
|
return "rejected by user"
|
||||||
|
}
|
||||||
|
return "rejected by user: " + strings.TrimSpace(e.reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHumanRejectError(reason string) error {
|
||||||
|
return &humanRejectError{reason: strings.TrimSpace(reason)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsHumanRejectError(err error) bool {
|
||||||
|
var target *humanRejectError
|
||||||
|
return errors.As(err, &target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithHITLToolInterceptor(ctx context.Context, fn HITLToolInterceptor) context.Context {
|
||||||
|
if fn == nil {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
return context.WithValue(ctx, hitlInterceptorKey{}, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func hitlToolCallMiddleware() compose.InvokableToolMiddleware {
|
||||||
|
return func(next compose.InvokableToolEndpoint) compose.InvokableToolEndpoint {
|
||||||
|
return func(ctx context.Context, input *compose.ToolInput) (*compose.ToolOutput, error) {
|
||||||
|
if input != nil {
|
||||||
|
if fn, ok := ctx.Value(hitlInterceptorKey{}).(HITLToolInterceptor); ok && fn != nil {
|
||||||
|
edited, err := fn(ctx, input.Name, input.Arguments)
|
||||||
|
if err != nil {
|
||||||
|
if IsHumanRejectError(err) {
|
||||||
|
// Human rejection should be a soft tool result so the model can continue iterating.
|
||||||
|
msg := fmt.Sprintf("[HITL Reject] Tool '%s' was rejected by human reviewer. Reason: %s\nPlease adjust parameters/plan and continue without this call.",
|
||||||
|
input.Name, strings.TrimSpace(err.Error()))
|
||||||
|
// transfer_to_agent 在 Eino 中标记为 returnDirectly:工具成功后 ReAct 子图会直接 END,
|
||||||
|
// 并依赖真实工具内的 SendToolGenAction 触发移交。HITL 拒绝时不会执行真实工具,
|
||||||
|
// 若仍走 returnDirectly 分支,监督者会在无 Transfer 动作的情况下结束,模型不再迭代。
|
||||||
|
if strings.EqualFold(strings.TrimSpace(input.Name), adk.TransferToAgentToolName) {
|
||||||
|
_ = compose.ProcessState[*adk.State](ctx, func(_ context.Context, st *adk.State) error {
|
||||||
|
if st == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
st.ReturnDirectlyToolCallID = ""
|
||||||
|
st.HasReturnDirectly = false
|
||||||
|
st.ReturnDirectlyEvent = nil
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return &compose.ToolOutput{Result: msg}, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if edited != "" {
|
||||||
|
input.Arguments = edited
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return next(ctx, input)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -268,6 +268,7 @@ func RunDeepAgent(
|
|||||||
Tools: subToolsForCfg,
|
Tools: subToolsForCfg,
|
||||||
UnknownToolsHandler: einomcp.UnknownToolReminderHandler(),
|
UnknownToolsHandler: einomcp.UnknownToolReminderHandler(),
|
||||||
ToolCallMiddlewares: []compose.ToolMiddleware{
|
ToolCallMiddlewares: []compose.ToolMiddleware{
|
||||||
|
{Invokable: hitlToolCallMiddleware()},
|
||||||
{Invokable: softRecoveryToolCallMiddleware()},
|
{Invokable: softRecoveryToolCallMiddleware()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -366,6 +367,7 @@ func RunDeepAgent(
|
|||||||
Tools: mainToolsForCfg,
|
Tools: mainToolsForCfg,
|
||||||
UnknownToolsHandler: einomcp.UnknownToolReminderHandler(),
|
UnknownToolsHandler: einomcp.UnknownToolReminderHandler(),
|
||||||
ToolCallMiddlewares: []compose.ToolMiddleware{
|
ToolCallMiddlewares: []compose.ToolMiddleware{
|
||||||
|
{Invokable: hitlToolCallMiddleware()},
|
||||||
{Invokable: softRecoveryToolCallMiddleware()},
|
{Invokable: softRecoveryToolCallMiddleware()},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user