Source code for ralph.pro_support.env

"""Pro contract env var readers.

The Pro↔Ralph contract (see
``Ralph-Workflow-Pro/docs/product-spec/CONTRACT_RALPH_INTEGRATION.md``
§3) limits Ralph-Workflow-Pro to setting exactly three engine-facing
environment variables on the subprocess:

- ``RALPH_WORKFLOW_PRO`` — non-empty truthy marker that the engine uses to
  detect "we are a Pro subprocess."
- ``RALPH_WORKSPACE`` — absolute or relative path to the workspace root.
  When set, the engine must prefer this over the current working
  directory when resolving the workspace scope.
- ``PROMPT_PATH`` — absolute or relative path to the operator-visible
  source prompt file. When set, the engine must prefer this over
  ``<workspace>/PROMPT.md``.

The contract explicitly states the engine MUST NOT require any
additional variables. Run identifiers, heartbeat tokens, ports, and
other Pro-owned metadata are delivered through a Pro-owned marker file
at ``<workspace>/.ralph/run.json`` (see :mod:`ralph.pro_support.marker`).

Each helper in this module is a *pure* function. None of them perform
I/O. Each accepts an optional ``env`` mapping so tests can inject values
without monkeypatching ``os.environ``.
"""

from __future__ import annotations

import os
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from collections.abc import Mapping


RALPH_WORKFLOW_PRO = "RALPH_WORKFLOW_PRO"
RALPH_WORKSPACE = "RALPH_WORKSPACE"
PROMPT_PATH = "PROMPT_PATH"


def _get_env(env: Mapping[str, str] | None) -> Mapping[str, str]:
    """Return the supplied ``env`` mapping or ``os.environ`` when omitted.

    Centralises the "default to os.environ" pattern so every helper has
    the same behaviour and tests can inject without monkeypatching.
    """
    return os.environ if env is None else env


[docs] def is_pro_mode(env: Mapping[str, str] | None = None) -> bool: """Return True when ``RALPH_WORKFLOW_PRO`` is set to a truthy value. "Truthy" here is a non-empty string. The contract does not specify a particular value; any non-empty value indicates Pro-mode. Args: env: Optional env mapping. When ``None`` (default), ``os.environ`` is read at call time. """ return bool(_get_env(env).get(RALPH_WORKFLOW_PRO))
[docs] def get_ralph_workspace(env: Mapping[str, str] | None = None) -> str | None: """Return the raw ``RALPH_WORKSPACE`` value, or ``None`` if unset/empty. This is a thin accessor; the canonical Path-aware resolver is :func:`ralph.pro_support.workspace.resolve_pro_workspace`. Args: env: Optional env mapping. When ``None`` (default), ``os.environ`` is read at call time. """ value = _get_env(env).get(RALPH_WORKSPACE, "") if not value: return None return value
[docs] def get_prompt_path(env: Mapping[str, str] | None = None) -> str | None: """Return the raw ``PROMPT_PATH`` value, or ``None`` if unset/empty. This is a thin accessor; the canonical Path-aware resolver is :func:`ralph.pro_support.prompt.resolve_effective_prompt_path`. Args: env: Optional env mapping. When ``None`` (default), ``os.environ`` is read at call time. """ value = _get_env(env).get(PROMPT_PATH, "") if not value: return None return value
__all__ = [ "PROMPT_PATH", "RALPH_WORKFLOW_PRO", "RALPH_WORKSPACE", "get_prompt_path", "get_ralph_workspace", "is_pro_mode", ]