""" Writable directory resolution for the agent. These are shared infrastructure constants — an env-resolved input/output/cache location — needed by both the ``tools`` layer (which writes analysis artifacts) and the ``workflows`` layer (which writes combined datasets). They live in ``core`` so both layers can import them downward without violating the layering contract (``tools`` and ``workflows`` both build on ``core``). """ from __future__ import annotations import os from pathlib import Path # core/paths.py lives at /src/core/, so two levels up is /src — # the same base directory the tool package historically resolved against. PROJECT_ROOT = Path(__file__).parent.parent.resolve() _DEFAULT_INPUT = PROJECT_ROOT / "tmp" / "inputs" _DEFAULT_OUTPUT = PROJECT_ROOT / "tmp" / "outputs" _DEFAULT_GEO_CACHE = PROJECT_ROOT / "tmp" / "geo_cache" def _resolve_dir(env_var: str, project_default: Path, hf_fallback: Path) -> Path: """Return a writable directory: env var > project default > /tmp fallback.""" env_val = os.environ.get(env_var) if env_val: p = Path(env_val) p.mkdir(parents=True, exist_ok=True) return p try: project_default.mkdir(parents=True, exist_ok=True) return project_default except PermissionError: hf_fallback.mkdir(parents=True, exist_ok=True) return hf_fallback INPUT_DIR = _resolve_dir("RNA_INPUT_DIR", _DEFAULT_INPUT, Path("/tmp/decoupleRpy/inputs")) OUTPUT_DIR = _resolve_dir("RNA_OUTPUT_DIR", _DEFAULT_OUTPUT, Path("/tmp/decoupleRpy/outputs")) GEO_CACHE_DIR = _resolve_dir( "RNA_GEO_CACHE_DIR", _DEFAULT_GEO_CACHE, Path("/tmp/decoupleRpy/geo_cache") )