Open-source release of MAESTRO, an agent orchestration platform that runs LLM-driven tasks through sandboxed tools, with a web UI. Apache-2.0. See README.md and docs/ (getting-started, configuration, architecture).
79 lines
3.0 KiB
Bash
Executable File
79 lines
3.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Pre-bake the Python packages the agent Bash sandbox needs.
|
|
#
|
|
# These are installed into the SYSTEM python's site-packages, because that is
|
|
# what bwrap read-only bind-mounts (/usr) into every Bash sandbox. A `--user`
|
|
# install (~/.local) is NOT visible inside the sandbox (/home is not mounted),
|
|
# so it must be a system install.
|
|
#
|
|
# Idempotent and safe to re-run. Non-fatal by default (prints a warning and
|
|
# exits 0 so it does not break a build); pass --strict to fail on error.
|
|
#
|
|
# See docs/operations/bash-sandbox-provisioning.md.
|
|
set -uo pipefail
|
|
|
|
PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
REQ="$PROJECT_DIR/runtime/python-requirements.txt"
|
|
STRICT=0
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--strict) STRICT=1 ;;
|
|
-h|--help) echo "Usage: $0 [--strict]"; exit 0 ;;
|
|
*) echo "Unknown option: $arg" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
soft_fail() {
|
|
echo "[prebake-python] $1" >&2
|
|
if [ "$STRICT" -eq 1 ]; then exit 1; fi
|
|
echo "[prebake-python] continuing (non-strict); Bash-tool python packages may be unavailable." >&2
|
|
exit 0
|
|
}
|
|
|
|
[ -f "$REQ" ] || soft_fail "requirements file not found: $REQ"
|
|
|
|
if command -v pip3 >/dev/null 2>&1; then PIP="pip3"
|
|
elif command -v pip >/dev/null 2>&1; then PIP="pip"
|
|
elif command -v python3 >/dev/null 2>&1; then PIP="python3 -m pip"
|
|
else soft_fail "no pip / python3 found — skipping python pre-bake"; fi
|
|
|
|
echo "[prebake-python] installing $REQ into the system python via: $PIP"
|
|
|
|
# PEP668 distros (Debian/Ubuntu/alpine) mark the system python "externally
|
|
# managed"; --break-system-packages is required there. Older pip rejects that
|
|
# flag, so retry without it.
|
|
if $PIP install --break-system-packages -r "$REQ"; then
|
|
:
|
|
elif $PIP install -r "$REQ"; then
|
|
:
|
|
else
|
|
soft_fail "pip install failed. If this is a permission error, retry as: sudo $PIP install --break-system-packages -r runtime/python-requirements.txt"
|
|
fi
|
|
|
|
echo "[prebake-python] done. Verifying imports..."
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
python3 - <<'PYEOF' || echo "[prebake-python] WARNING: some packages failed to import (see above)." >&2
|
|
import importlib, sys
|
|
# import-name : pip-name (for the warning message)
|
|
mods = {
|
|
"pypdf": "pypdf", "fitz": "pymupdf", "pdfplumber": "pdfplumber",
|
|
"docx": "python-docx", "pptx": "python-pptx", "openpyxl": "openpyxl",
|
|
"xlsxwriter": "xlsxwriter", "xlrd": "xlrd", "odf": "odfpy", "striprtf": "striprtf",
|
|
"bs4": "beautifulsoup4", "lxml": "lxml", "markdownify": "markdownify",
|
|
"markdown": "markdown", "numpy": "numpy", "pandas": "pandas", "tabulate": "tabulate",
|
|
"dateutil": "python-dateutil", "matplotlib": "matplotlib", "PIL": "Pillow",
|
|
"charset_normalizer": "charset-normalizer", "yaml": "PyYAML",
|
|
}
|
|
missing = []
|
|
for mod, pkg in mods.items():
|
|
try:
|
|
importlib.import_module(mod)
|
|
except Exception:
|
|
missing.append(f"{pkg} (import {mod})")
|
|
if missing:
|
|
print("[prebake-python] MISSING: " + ", ".join(missing), file=sys.stderr)
|
|
sys.exit(1)
|
|
print(f"[prebake-python] all {len(mods)} packages import OK.")
|
|
PYEOF
|
|
fi
|