hmgill/CXR-Agent
1
1# cxr-agent/tools/context.py2"""3tools/context.py4================5Run-scoped state for the CXR agent's sandbox visualization path.6 7Why this exists8---------------9The CXR pipeline tools (`triage_image`, `encode_image`, `localize_findings`,10`speak_findings`) are self-contained: they take a file path / JSON string and11return a value, so they never needed a shared context object. The sandbox12visualization path is different — it provisions a sandbox **once per13conversation** and reuses it across turns, and it needs somewhere to record the14output directory and which overlay files have already been produced.15 16``CXRContext`` is that shared state. It is deliberately tiny: it holds only the17sandbox-relevant fields (mirroring the subset of OCT's ``OCTContext`` that the18overlay path actually uses). The image itself stays on disk and is addressed by19path, and the finding boxes are small enough to pass as tool arguments, so —20unlike OCT — there is no image/artifact handle store here.21 22Pass it to the runner once::23 24 octx = CXRContext(output_dir="/tmp/cxr_out/<session>")25 await Runner.run(agent, input=..., context=octx)26 27Inside any ``@function_tool`` it is reachable as ``ctx.context``. The sandbox28tools tolerate ``ctx.context is None`` (they fall back to a default output dir29and a fresh on-demand sandbox), so adding ``context=`` never breaks the existing30context-free tools — they simply ignore it.31"""32 33from __future__ import annotations34 35import os36from dataclasses import dataclass, field37from typing import Any, Optional38 39 40def _default_out_dir() -> str:41 return os.environ.get("CXR_OUT_DIR", "/tmp/cxr_out")42 43 44@dataclass45class CXRContext:46 """47 The object handed to ``Runner.run(..., context=...)`` for the sandbox path.48 49 Attributes:50 output_dir: Host directory where collected overlay HTML is written.51 sandbox: A lazily-provisioned ``SandboxManager`` for the on-demand52 ``render_finding_overlay`` tool (created on first use).53 sandbox_session: A live sandbox session injected by the runner for the54 advanced, model-driven ``SandboxAgent`` path (set via ``RunConfig``).55 overlays: Filenames of overlay HTML produced so far this run.56 """57 58 output_dir: str = field(default_factory=_default_out_dir)59 sandbox: Optional[Any] = None # SandboxManager (lazy, on-demand path)60 sandbox_session: Optional[Any] = None # live session (model-driven path)61 overlays: list = field(default_factory=list)62 