"""Per-turn, request-scoped state shared between the bridge, the reply engine and tools — without threading extra parameters through the whole engine call chain (run_reply_engine -> run_tool_with_retries -> execute_tool -> execute). Flask serves each HTTP request on its own thread and the reply engine + tools run synchronously on that thread, so a ``threading.local`` cleanly scopes a single turn. Anything that can't see the thread-local (a worker thread, an eval, a unit test) just reads ``None`` and the caller falls back to its default. Fields ------ broadcasting : Optional[bool] The live screen-share (Go-Live) state the bot sends with the request. The webSearch routing reads it to pick on-screen Chrome (live) vs Gemini (off). broadcast_action : Optional[str] A directive ("start"/"stop") recorded by the setBroadcast tool for the bridge to return to the bot, which owns the actual broadcast. """ from __future__ import annotations import threading from typing import Optional _state = threading.local() def reset() -> None: """Clear per-turn state. Call at the start of each request.""" _state.broadcasting = None _state.broadcast_action = None def set_broadcasting(value: Optional[bool]) -> None: _state.broadcasting = value def get_broadcasting() -> Optional[bool]: return getattr(_state, "broadcasting", None) def request_broadcast(action: str) -> None: """Record a broadcast directive. ``action`` is "start" or "stop".""" _state.broadcast_action = action def get_broadcast_action() -> Optional[str]: return getattr(_state, "broadcast_action", None)