"""Shared sibling-module loader for the auto-agents Python tooling. Every driver and runtime helper in :mod:`tools` needs to load its peer modules without forcing callers to install the package. The historical pattern was to redeclare ``_load_sibling`` in each entry point; that left three independent copies in ``_dispatch_runtime.py``, ``dispatch_review.py``, and ``dispatch_implementer.py`` (plus near-identical copies elsewhere). This module collapses those copies into one helper. Behavior is identical: load by file path relative to ``tools/``, cache the result in :data:`sys.modules` under the requested name, and return the cached instance on subsequent calls. """ from __future__ import annotations import importlib.util import sys from pathlib import Path from types import ModuleType TOOLS_DIR = Path(__file__).resolve().parent def load_sibling(module_name: str, filename: str) -> ModuleType: """Load ``filename`` from ``tools/`` as ``module_name``. Returns the cached module from :data:`sys.modules` if already loaded; otherwise compiles and registers a fresh instance. Used by drivers that need to import other ``tools/`` files without making ``tools`` an installable package. """ cached = sys.modules.get(module_name) if cached is not None: return cached path = TOOLS_DIR / filename if not path.exists(): # ``spec_from_file_location`` happily builds a spec for a # non-existent path and only raises ``FileNotFoundError`` from # ``exec_module``, which is confusing to operators reading a # traceback. Surface a clean ``ImportError`` up front. raise ImportError( f"cannot load sibling {module_name!r}: file does not exist at {path}" ) spec = importlib.util.spec_from_file_location(module_name, path) if spec is None or spec.loader is None: raise ImportError(f"cannot build module spec for {module_name} at {path}") mod = importlib.util.module_from_spec(spec) sys.modules[module_name] = mod spec.loader.exec_module(mod) return mod