242 lines
8.1 KiB
Bash
Executable file
242 lines
8.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
# band-aider: load the local Band-Aider environment and launch the CLI.
|
|
#
|
|
# Examples:
|
|
# --tests-root tests --task "Fix the issue"
|
|
# --src-root package --tests-root tests
|
|
#
|
|
# The final exec is the only application subprocess: it preserves the exact
|
|
# CLI exit status. Optional Model2Vec checks run before it to select an
|
|
# accelerator or explain the full-file-parser fallback.
|
|
|
|
set -uo pipefail
|
|
|
|
REPO_ROOT=""
|
|
REPO_CONTAINER=""
|
|
|
|
LAUNCHER_ARG_INDEX=1
|
|
while [ "$LAUNCHER_ARG_INDEX" -le "$#" ]; do
|
|
case "${!LAUNCHER_ARG_INDEX}" in
|
|
--repo-root)
|
|
NEXT_INDEX=$((LAUNCHER_ARG_INDEX + 1))
|
|
REPO_ROOT="${!NEXT_INDEX:-}"
|
|
LAUNCHER_ARG_INDEX=$((LAUNCHER_ARG_INDEX + 2))
|
|
;;
|
|
--repo-container)
|
|
NEXT_INDEX=$((LAUNCHER_ARG_INDEX + 1))
|
|
REPO_CONTAINER="${!NEXT_INDEX:-}"
|
|
LAUNCHER_ARG_INDEX=$((LAUNCHER_ARG_INDEX + 2))
|
|
;;
|
|
--task)
|
|
LAUNCHER_ARG_INDEX=$((LAUNCHER_ARG_INDEX + 2))
|
|
;;
|
|
*)
|
|
LAUNCHER_ARG_INDEX=$((LAUNCHER_ARG_INDEX + 1))
|
|
;;
|
|
esac
|
|
done
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/band-aider --task "goal" [--src-root src] [--tests-root tests] [band-aider args...]
|
|
scripts/band-aider --resume
|
|
|
|
Loads Band-Aider environment settings, then runs the current SupremeLoop CLI.
|
|
USAGE
|
|
}
|
|
|
|
if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then
|
|
usage
|
|
exit 0
|
|
fi
|
|
|
|
ENV_FILE="${BAND_AIDER_ENV_FILE:-band-aider.env}"
|
|
|
|
# Load optional environment configuration only when the configured file exists.
|
|
if [ -f "$ENV_FILE" ]; then
|
|
set -a
|
|
|
|
# shellcheck disable=SC1090
|
|
. "$ENV_FILE"
|
|
|
|
set +a
|
|
fi
|
|
|
|
BAND_AIDER_TOKEN_OVERFLOW_STRATEGY="${BAND_AIDER_TOKEN_OVERFLOW_STRATEGY:-miser}"
|
|
PYTHON_BIN="${BAND_AIDER_PYTHON_BIN:-python3}"
|
|
|
|
if [ -n "$REPO_ROOT" ]; then
|
|
MEMENTO_LIST_FILE="$(mktemp)"
|
|
trap 'rm -f "$MEMENTO_LIST_FILE"' EXIT
|
|
|
|
if [ -n "$REPO_CONTAINER" ]; then
|
|
if ! docker exec "$REPO_CONTAINER" find "$REPO_ROOT" \
|
|
-type f \
|
|
-not -path "$REPO_ROOT/.git/*" \
|
|
-regextype posix-extended \
|
|
-regex '.*/\.[^/]+~[0-9]*$' \
|
|
-print0 >"$MEMENTO_LIST_FILE"; then
|
|
echo "Could not scan Memento files in container: $REPO_CONTAINER" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
if ! find "$REPO_ROOT" \
|
|
-type f \
|
|
-not -path "$REPO_ROOT/.git/*" \
|
|
-regextype posix-extended \
|
|
-regex '.*/\.[^/]+~[0-9]*$' \
|
|
-print0 >"$MEMENTO_LIST_FILE"; then
|
|
echo "Could not scan Memento files under: $REPO_ROOT" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
MEMENTO_FILES=()
|
|
while IFS= read -r -d '' MEMENTO_FILE; do
|
|
MEMENTO_FILES+=("$MEMENTO_FILE")
|
|
done <"$MEMENTO_LIST_FILE"
|
|
|
|
if [ "${#MEMENTO_FILES[@]}" -gt 0 ]; then
|
|
echo "Found stale Band-Aider Memento files:"
|
|
printf ' %s\n' "${MEMENTO_FILES[@]}"
|
|
|
|
read -r -p "Clear stale Band-Aider Memento files before starting? [y/N]: " CLEAR_MEMENTOS
|
|
|
|
case "$CLEAR_MEMENTOS" in
|
|
[Yy] | [Yy][Ee][Ss])
|
|
for MEMENTO_FILE in "${MEMENTO_FILES[@]}"; do
|
|
if [ -n "$REPO_CONTAINER" ]; then
|
|
if ! docker exec "$REPO_CONTAINER" rm -- "$MEMENTO_FILE"; then
|
|
echo "Could not delete Memento file in container: $MEMENTO_FILE" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
if ! rm -- "$MEMENTO_FILE"; then
|
|
echo "Could not delete Memento file: $MEMENTO_FILE" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
done
|
|
|
|
if [ -n "$REPO_CONTAINER" ]; then
|
|
if ! docker exec "$REPO_CONTAINER" find "$REPO_ROOT" \
|
|
-type f \
|
|
-not -path "$REPO_ROOT/.git/*" \
|
|
-regextype posix-extended \
|
|
-regex '.*/\.[^/]+~[0-9]*$' \
|
|
-print0 >"$MEMENTO_LIST_FILE"; then
|
|
echo "Could not verify Memento cleanup in container: $REPO_CONTAINER" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
if ! find "$REPO_ROOT" \
|
|
-type f \
|
|
-not -path "$REPO_ROOT/.git/*" \
|
|
-regextype posix-extended \
|
|
-regex '.*/\.[^/]+~[0-9]*$' \
|
|
-print0 >"$MEMENTO_LIST_FILE"; then
|
|
echo "Could not verify Memento cleanup under: $REPO_ROOT" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [ -s "$MEMENTO_LIST_FILE" ]; then
|
|
echo "Memento files remain after cleanup; aborting." >&2
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
echo "Stale Memento cleanup declined; aborting."
|
|
exit 1
|
|
;;
|
|
esac
|
|
fi
|
|
fi
|
|
|
|
# Verify the selected interpreter before any optional capability checks.
|
|
if ! command -v "$PYTHON_BIN" >/dev/null 2>&1; then
|
|
echo "Python interpreter not found: $PYTHON_BIN"
|
|
exit 1
|
|
fi
|
|
|
|
# The two branches below select Model2Vec when installed and cached; otherwise
|
|
# they deliberately retain the supported full-file parsing behavior.
|
|
if ! "$PYTHON_BIN" -c '
|
|
from band_aider.judgement.model2vec_code_parser import model2vec_package_available
|
|
import sys
|
|
|
|
sys.exit(0 if model2vec_package_available() else 1)
|
|
' >/dev/null 2>&1; then
|
|
echo "model2vec is not installed for $PYTHON_BIN."
|
|
echo "Band-Aider will fall back to full-file parsing."
|
|
echo 'Install the optional accelerator with: pip install -e ".[model2vec]"'
|
|
else
|
|
MODEL2VEC_INFO="$(
|
|
"$PYTHON_BIN" -c '
|
|
from band_aider.judgement.model2vec_code_parser import (
|
|
MODEL2VEC_MODEL_NAME,
|
|
default_model2vec_cache_dir,
|
|
)
|
|
|
|
print(MODEL2VEC_MODEL_NAME)
|
|
print(default_model2vec_cache_dir())
|
|
'
|
|
)"
|
|
|
|
MODEL2VEC_NAME="$(printf '%s\n' "$MODEL2VEC_INFO" | sed -n '1p')"
|
|
MODEL2VEC_CACHE_DIR="$(printf '%s\n' "$MODEL2VEC_INFO" | sed -n '2p')"
|
|
|
|
# A missing cache is nonfatal: interactive users may download it, while
|
|
# noninteractive benchmark runs continue without prompting.
|
|
if ! "$PYTHON_BIN" -c '
|
|
from band_aider.judgement.model2vec_code_parser import model2vec_model_cached
|
|
import sys
|
|
|
|
sys.exit(0 if model2vec_model_cached() else 1)
|
|
' >/dev/null 2>&1; then
|
|
if [ ! -t 0 ]; then
|
|
echo "Model2Vec model cache is missing for $MODEL2VEC_NAME."
|
|
echo "Band-Aider will fall back to full-file parsing."
|
|
else
|
|
echo "Band-Aider can use a local Model2Vec gate for narrow file parsing."
|
|
echo "Missing model cache: $MODEL2VEC_NAME"
|
|
echo "Cache root: $MODEL2VEC_CACHE_DIR"
|
|
|
|
read -r -p "Download the Model2Vec cache now? [y/N]: " download_model2vec
|
|
|
|
# The response branch either downloads the optional cache or records why
|
|
# the fallback remains active; neither branch changes loop behavior.
|
|
case "$download_model2vec" in
|
|
[Yy] | [Yy][Ee][Ss])
|
|
if ! "$PYTHON_BIN" -c '
|
|
from band_aider.judgement.model2vec_code_parser import (
|
|
ensure_model2vec_model_downloaded,
|
|
)
|
|
|
|
ensure_model2vec_model_downloaded()
|
|
'; then
|
|
echo "Failed to download $MODEL2VEC_NAME."
|
|
echo "Band-Aider will fall back to full-file parsing."
|
|
fi
|
|
;;
|
|
*)
|
|
echo "Model2Vec download declined."
|
|
echo "Band-Aider will fall back to full-file parsing."
|
|
;;
|
|
esac
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
export BAND_AIDER_TOKEN_OVERFLOW_STRATEGY
|
|
|
|
EXTRA_ARGS=(--log-to-console)
|
|
|
|
# Forward the persistent repository container name/ID when provided. This is
|
|
# the call-site boundary that keeps container execution inside the CLI adapter.
|
|
if [ -n "${BAND_AIDER_REPO_CONTAINER:-}" ]; then
|
|
EXTRA_ARGS+=("--repo-container" "$BAND_AIDER_REPO_CONTAINER")
|
|
fi
|
|
|
|
exec "$PYTHON_BIN" -m band_aider.cli "${EXTRA_ARGS[@]}" "$@"
|