package loop import "context" // loopSessionIDKey 是当前 Run 所驱动 session id 的 context key。 // 它在 Run 顶部播种,并在循环发出会话级 UI 事件 // (capacity_awaken)处读取,使事件携带正确的会话, // 而不是被当作全局事件。 type loopSessionIDKey struct{} // withLoopSession 返回携带 Run 会话 id 的 context。 func withLoopSession(ctx context.Context, sessionID string) context.Context { return context.WithValue(ctx, loopSessionIDKey{}, sessionID) } // loopSession 返回 ctx 上的 session id;未播种时返回 ""(为在 // Run 之外驱动循环的调用方提供的防御性兜底)。 func loopSession(ctx context.Context) string { s, _ := ctx.Value(loopSessionIDKey{}).(string) return s } // SessionFromContext 返回外层 Run 所驱动的 session id;未挂载时 // 返回 ""。它导出是为了让循环内执行的工具能把其启动的工作 // (派生的子代理、后台任务)归属到发起它的会话 —— 绝不 // 从模型输出推断。 func SessionFromContext(ctx context.Context) string { return loopSession(ctx) } // loopTurnIDKey 是当前 Run 正在产出的 assistant turn 的 context key。 // gateway 在开始一个 turn 前挂载它(WithTurnID),使循环发出的 // 流式事件能被客户端关联到该 turn。 type loopTurnIDKey struct{} // WithTurnID 把 turnID 挂到 ctx 上,使循环发出的流式事件携带 // 所属的 turn。它导出是因为 gateway 每个 turn 在 Run 之前调用一次; // 未挂载的调用方会让事件的 TurnID 为空, // 从而保持关联字段向后兼容。 func WithTurnID(ctx context.Context, turnID string) context.Context { return context.WithValue(ctx, loopTurnIDKey{}, turnID) } // loopTurn 返回 ctx 上的 turn id;未挂载时返回 ""。 func loopTurn(ctx context.Context) string { s, _ := ctx.Value(loopTurnIDKey{}).(string) return s }