42 lines
1.7 KiB
Go
42 lines
1.7 KiB
Go
package loop
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
)
|
|
|
|
// subagentTaskKey 是「本 Run 由编排器作为子代理派发、并携带派给它的任务目标」的
|
|
// context key。
|
|
type subagentTaskKey struct{}
|
|
|
|
// WithSubagentTask 把一次子代理派发的**任务目标**挂到该次 Run 的 context 上。
|
|
// 它由编排层在驱动子代理 Run 之前挂载(见 orchestration 的 Scheduler.run,与
|
|
// WithToolWhitelist / WithFlowBranch 同一处、同一族),是「本次工具调用是否由
|
|
// 子代理发起、为了什么任务」的**结构化信号**。
|
|
//
|
|
// 敏感操作代审的越界判定只读这条信号,绝不从提示词、模型文本或会话 id 形态推断
|
|
// (项目红线:身份与归属靠元数据)。空 goal 是空操作:未派发的运行(主会话自身、
|
|
// 后台思考)不挂该键,读侧得到 ok=false,语义为「非子代理发起」。
|
|
func WithSubagentTask(ctx context.Context, goal string) context.Context {
|
|
if ctx == nil || strings.TrimSpace(goal) == "" {
|
|
return ctx
|
|
}
|
|
return context.WithValue(ctx, subagentTaskKey{}, goal)
|
|
}
|
|
|
|
// SubagentTaskFrom 返回 ctx 上挂着的派发任务目标;未挂载(或目标为空白)时返回
|
|
// ok=false。它是 WithSubagentTask 的读侧,供拿到 context 的调用方(工具准入钩子、
|
|
// 代审判定器)识别「这次调用由子代理发起」,并拿到判「有没有越界」所需的那个任务。
|
|
//
|
|
// 它的签名与 audit.SubagentOrigin 一致,组合根因此可以直接把它当来源解析器注入。
|
|
func SubagentTaskFrom(ctx context.Context) (string, bool) {
|
|
if ctx == nil {
|
|
return "", false
|
|
}
|
|
goal, _ := ctx.Value(subagentTaskKey{}).(string)
|
|
if strings.TrimSpace(goal) == "" {
|
|
return "", false
|
|
}
|
|
return goal, true
|
|
}
|