package loop import ( "context" "git.yeij.top/AskaEth/Cyrene_v2/internal/capability/restrict" ) // SessionEnv 是每次 Run 调用中控制记忆注入与 // 提取的按会话上下文。它挂在调用的 context 上而不是 // 共享的 Loop 上,因为 Loop 会在并发会话间复用(每条 // channel/群聊/陌生人消息都解析出自己的隔离边界);把它 // 存在 Loop 结构体上会产生数据竞争。 type SessionEnv struct { // ActorEnv 是解析出的 actor 环境:owner、group_member、stranger。 // 它是由 channel 层结构化判定的强类型身份车道 //(design/11 §0),绝不从提示词文本推断。 ActorEnv restrict.ActorEnv // MemWritable 报告该会话是否可以写共享记忆。它仅 // 在主人的私聊中为 true;群聊与陌生人 // 只读(design/02 §3, design/11 §2)。 MemWritable bool // PersonaID 是该会话发言所作为的角色(design/22 §2/§4.2),由调用方 // 每 turn 解析(通常是 gateway 的会话绑定解析器)。为空 // 表示「继承循环配置的角色」(Options.PersonaID,全局默认 // 角色),这使所有多角色之前的调用方 —— channelbridge、backthink、 // 内部自主流程 —— 行为与从前完全一致。它界定系统 // 提示词、记忆命名空间、情绪机与思考预算的作用域;它 // 不是身份或权限输入:仅由 ActorEnv/MemWritable 决定访问 // (项目红线)。 PersonaID string } // Restricted 报告这是否为群聊或陌生人会话,即 // 只读记忆隔离上下文。由于 MemWritable 仅在 // 主人的私聊中为 true,!MemWritable 恰好就是受限集合。 func (e SessionEnv) Restricted() bool { return !e.MemWritable } // OwnerEnv 返回全权限的主人会话环境(私聊, // 记忆读写)。它是 Web 主会话与内部 // 自动化任务的默认值,与既有的 owner 全权限行为一致。它不绑定 // 显式角色(PersonaID 为空),因此循环回退到其配置的 // 默认角色 —— 知道会话角色的调用方在返回值上 // 设置 PersonaID(design/22 §4.2)。 func OwnerEnv() SessionEnv { return SessionEnv{ActorEnv: restrict.ActorOwner, MemWritable: true} } // defaultSessionEnv 是调用方未挂载显式 env 时使用的 // owner 全权限环境:记忆全读写,即既有行为。 func defaultSessionEnv() SessionEnv { return OwnerEnv() } type sessionEnvKey struct{} // WithSessionEnv 把 env 挂到 ctx 上,使 Run 的记忆门按调用遵循 // 群聊/陌生人只读隔离。它是并发安全的:env // 随调用的 context 传递,绝不存放在共享的 Loop 上。 func WithSessionEnv(ctx context.Context, env SessionEnv) context.Context { return context.WithValue(ctx, sessionEnvKey{}, env) } // SessionEnvFrom 返回 WithSessionEnv 挂到 ctx 上的环境; // 未挂载时返回 owner 全权限默认值(向后兼容)。它是 // WithSessionEnv 的读侧,供只拿到 context 的调用方使用 —— 例如 // 必须知道该 turn 角色/隔离边界的 Chatter 实现,或 // 断言某入站路径解析结果的测试。该值仅是展示/作用域元数据: // 身份与权限在 env 存在之前就已由 actor 元数据决定 // (项目红线)。 func SessionEnvFrom(ctx context.Context) SessionEnv { return sessionEnvFrom(ctx) } // sessionEnvFrom 返回挂到 ctx 上的 env;未挂载时返回 // owner 全权限默认值(向后兼容)。 func sessionEnvFrom(ctx context.Context) SessionEnv { if ctx == nil { return defaultSessionEnv() } if env, ok := ctx.Value(sessionEnvKey{}).(SessionEnv); ok { return env } return defaultSessionEnv() }