mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-03-31 08:19:54 +02:00
63 lines
2.2 KiB
Go
63 lines
2.2 KiB
Go
package multiagent
|
||
|
||
import (
|
||
"context"
|
||
"strings"
|
||
|
||
"github.com/cloudwego/eino/adk"
|
||
"github.com/cloudwego/eino/components/tool"
|
||
)
|
||
|
||
// noNestedTaskMiddleware 禁止在已经处于 task(sub-agent) 执行链中再次调用 task,
|
||
// 避免子代理再次委派子代理造成的无限委派/递归。
|
||
//
|
||
// 通过在 ctx 中设置临时标记来实现嵌套检测:外层 task 调用会先标记 ctx,
|
||
// 子代理内再调用 task 时会命中该标记并拒绝。
|
||
type noNestedTaskMiddleware struct {
|
||
adk.BaseChatModelAgentMiddleware
|
||
}
|
||
|
||
type nestedTaskCtxKey struct{}
|
||
|
||
func newNoNestedTaskMiddleware() adk.ChatModelAgentMiddleware {
|
||
return &noNestedTaskMiddleware{}
|
||
}
|
||
|
||
func (m *noNestedTaskMiddleware) WrapInvokableToolCall(
|
||
ctx context.Context,
|
||
endpoint adk.InvokableToolCallEndpoint,
|
||
tCtx *adk.ToolContext,
|
||
) (adk.InvokableToolCallEndpoint, error) {
|
||
if tCtx == nil || strings.TrimSpace(tCtx.Name) == "" {
|
||
return endpoint, nil
|
||
}
|
||
// Deep 内置 task 工具名固定为 "task";为兼容可能的大小写/空白,仅做不区分大小写匹配。
|
||
if !strings.EqualFold(strings.TrimSpace(tCtx.Name), "task") {
|
||
return endpoint, nil
|
||
}
|
||
|
||
// 已在 task 执行链中:拒绝继续委派,直接报错让上层快速终止。
|
||
if ctx != nil {
|
||
if v, ok := ctx.Value(nestedTaskCtxKey{}).(bool); ok && v {
|
||
return func(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error) {
|
||
// Important: return a tool result text (not an error) to avoid hard-stopping the whole multi-agent run.
|
||
// The nested task is still prevented from spawning another sub-agent, so recursion is avoided.
|
||
_ = argumentsInJSON
|
||
_ = opts
|
||
return "Nested task delegation is forbidden (already inside a sub-agent delegation chain) to avoid infinite delegation. Please continue the work using the current agent's tools.", nil
|
||
}, nil
|
||
}
|
||
}
|
||
|
||
// 标记当前 task 调用链,确保子代理内的再次 task 调用能检测到嵌套。
|
||
return func(ctx context.Context, argumentsInJSON string, opts ...tool.Option) (string, error) {
|
||
ctx2 := ctx
|
||
if ctx2 == nil {
|
||
ctx2 = context.Background()
|
||
}
|
||
ctx2 = context.WithValue(ctx2, nestedTaskCtxKey{}, true)
|
||
return endpoint(ctx2, argumentsInJSON, opts...)
|
||
}, nil
|
||
}
|
||
|