import os
import re
import sys
import platform
import subprocess
from pathlib import Path
_PKG_ROOT = Path(__file__).parent.parent.parent _RECURSION_GUARD = "YANA_RT_WRAPPER_ACTIVE"
_SELF_REALPATH = str(Path(__file__).resolve())
_MIN_YANA_RT_VERSION = (1, 0, 0)
_VERSION_RE = re.compile(r"(\d+)\.(\d+)\.(\d+)")
def _check_version_compat(binary: str) -> None:
try:
result = subprocess.run(
[binary, "--version"], capture_output=True, text=True, timeout=5
)
match = _VERSION_RE.search(result.stdout)
if not match:
return
found = tuple(int(part) for part in match.groups())
if found < _MIN_YANA_RT_VERSION:
min_str = ".".join(str(p) for p in _MIN_YANA_RT_VERSION)
found_str = ".".join(str(p) for p in found)
print(
f"yana-rt: warning — resolved binary reports version {found_str}, "
f"older than {min_str}. Some subcommands this yana-ai release's "
"docs describe may not exist in it. Run `cargo install yana-rt` "
"to upgrade, or set $YANA_RT_BIN to a newer build.",
file=sys.stderr,
)
except (OSError, subprocess.TimeoutExpired, ValueError):
return
def _platform_bin() -> Path:
plat = sys.platform arch = platform.machine().lower()
if arch in ("amd64", "x86_64"):
arch = "x86_64"
ext = ".exe" if plat == "win32" else ""
return _PKG_ROOT / "bin" / f"yana-rt-{plat}-{arch}{ext}"
def _usable(candidate: str | None) -> bool:
if not candidate:
return False
p = Path(candidate)
if not p.exists() or not os.access(p, os.X_OK):
return False
try:
real = str(p.resolve())
except (OSError, RuntimeError):
return False
return real != _SELF_REALPATH
def _find_binary() -> str | None:
override = os.environ.get("YANA_RT_BIN")
if override and _usable(override):
return override
import shutil
on_path = shutil.which("yana-rt")
if on_path and _usable(on_path):
return on_path
pb = _platform_bin()
if _usable(str(pb)):
return str(pb)
local = _PKG_ROOT / "target" / "release" / "yana-rt"
if _usable(str(local)):
return str(local)
return None
def _run(extra_args: list[str] | None = None) -> None:
if os.environ.get(_RECURSION_GUARD):
print(
"yana-rt: recursion detected — the wrapper was re-entered by a "
"child it spawned.\nA candidate (likely $YANA_RT_BIN or a $PATH "
"shim) resolves back to this wrapper.\nUnset YANA_RT_BIN, or "
"point it at a real compiled binary (e.g. ~/.cargo/bin/yana-rt).",
file=sys.stderr,
)
sys.exit(1)
binary = _find_binary()
if binary is None:
print(
"yana-rt: binary not found.\n\n"
"To install, run one of:\n"
f" cargo install --path {_PKG_ROOT} # build from source (requires Rust)\n"
" export YANA_RT_BIN=/path/to/yana-rt\n\n"
"Do NOT set YANA_RT_BIN to the output of `which yana-rt` — on a\n"
"pip install that path is this wrapper itself, not a compiled binary.",
file=sys.stderr,
)
sys.exit(1)
_check_version_compat(binary)
env = {**os.environ, _RECURSION_GUARD: "1"}
result = subprocess.run([binary] + (extra_args or []) + sys.argv[1:], env=env)
sys.exit(result.returncode)
def main() -> None:
_run()
def chat_main() -> None:
_run(["chat"])
if __name__ == "__main__":
main()