Files
multi-agent-mux/deploy/install_mam.sh
T

234 lines
7.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# ==============================================================================
# Multi-Agent Mux (MAM) Skill Installer
# Efficiently installs MAM orchestration rules & skills to another project.
# ==============================================================================
set -euo pipefail
# ANSI color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions for logs
log_info() { echo -e "${BLUE}[INFO]${NC} $*"; }
log_ok() { echo -e "${GREEN}[OK]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
show_help() {
cat <<EOF
Usage: $0 [options]
Options:
-t, --target <path> Target directory/project where MAM should be installed (defaults to current directory)
-f, --force Force copy AGENTS.md even if it already exists (backups are still made)
-h, --help Show this help message
EOF
}
TARGET_DIR="."
FORCE=0
# Parse CLI arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-t|--target)
TARGET_DIR="$2"
shift 2
;;
-f|--force)
FORCE=1
shift
;;
-h|--help)
show_help
exit 0
;;
*)
log_error "Unknown option: $1"
show_help
exit 1
;;
esac
done
# Resolve absolute path for source and target, tracking symlinks gracefully
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SRC_DIR="$(cd "$DIR/.." && pwd)"
# Ensure target directory exists
if [ ! -d "$TARGET_DIR" ]; then
log_info "Creating target directory: $TARGET_DIR"
mkdir -p "$TARGET_DIR"
fi
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
log_info "Installing MAM skills to target project: $TARGET_DIR"
log_info "Source directory resolved: $SRC_DIR"
if [ "$SRC_DIR" = "$TARGET_DIR" ]; then
log_error "Source and Target directories are the same! Cannot install to oneself."
exit 1
fi
# 1. Dependency Checks
log_info "Verifying host dependencies..."
DEPS=(herdr python3 rsync uuidgen)
MISSING_DEPS=()
for dep in "${DEPS[@]}"; do
if ! command -v "$dep" &>/dev/null; then
MISSING_DEPS+=("$dep")
fi
done
if [ ${#MISSING_DEPS[@]} -ne 0 ]; then
log_error "Missing required dependencies: ${MISSING_DEPS[*]}"
if [[ " ${MISSING_DEPS[*]} " == *" herdr "* ]]; then
log_error "To install herdr, please refer to the official installation guide:"
log_error " curl -fsSL https://herdr.dev/install.sh | sh"
fi
log_error "Please install them before using MAM."
exit 1
fi
# Check Python PyYAML and sqlite3 library (hard dependencies for registry parsing)
if ! python3 -c "import yaml, sqlite3" &>/dev/null; then
log_error "Python 'pyyaml' or built-in 'sqlite3' modules are missing (hard dependencies for session registry)."
log_error "Please run: pip install pyyaml"
exit 1
fi
log_ok "Dependency checks completed."
# 2. Copy .agents/ folder and config tools
log_info "Deploying orchestration rules & skills (.agents/)..."
mkdir -p "$TARGET_DIR/.agents"
# Sync rules and skills, avoiding copying temporary or system files
# Exclude git histories, reports, logs or internal runtime cache if any
rsync -a --exclude='.git/' --exclude='/reports/' --exclude='*.log' --exclude='__pycache__/' --exclude='*.pyc' "$SRC_DIR/.agents/" "$TARGET_DIR/.agents/"
log_ok "Deployed Rules and Skills under target's .agents/"
# Copy config templates and generate scripts (M-2)
if [ -f "$SRC_DIR/.env.example" ]; then
cp "$SRC_DIR/.env.example" "$TARGET_DIR/.env.example"
log_ok "Copied .env.example configuration template"
fi
if [ -f "$SRC_DIR/deploy/generate-env.sh" ]; then
mkdir -p "$TARGET_DIR/scripts"
cp "$SRC_DIR/deploy/generate-env.sh" "$TARGET_DIR/scripts/generate-env.sh"
chmod +x "$TARGET_DIR/scripts/generate-env.sh"
log_ok "Copied deploy/generate-env.sh helper tool"
fi
# Copy the user manual into the target's .agents/ (previously came via rsync of .agents/)
if [ -f "$SRC_DIR/deploy/INSTALL.md" ]; then
cp "$SRC_DIR/deploy/INSTALL.md" "$TARGET_DIR/.agents/INSTALL.md"
log_ok "Copied INSTALL.md user manual into target .agents/"
fi
# 3. Copy AGENTS.md to root or inject guidelines pointer
log_info "Configuring developer guidelines (AGENTS.md)..."
AGENTS_FILE="$TARGET_DIR/AGENTS.md"
MARKER_START="<!-- BEGIN MAM ORCHESTRATION -->"
MARKER_END="<!-- END MAM ORCHESTRATION -->"
if [ -f "$AGENTS_FILE" ]; then
if [ "$FORCE" -eq 1 ]; then
log_warn "AGENTS.md already exists in target project. Backing up and overwriting (--force)..."
cp "$AGENTS_FILE" "$AGENTS_FILE.bak.$(date +%s)"
cp "$SRC_DIR/AGENTS.md" "$AGENTS_FILE"
log_ok "Guidelines overwritten successfully."
else
if grep -Fq "$MARKER_START" "$AGENTS_FILE"; then
log_ok "MAM orchestration guidelines pointer already exists in AGENTS.md."
else
echo -e "\n$MARKER_START\n# 🤖 Multi-Agent Orchestration Guidelines\nPlease refer to [.agents/MULTI_AGENT_RULES.md](file://./.agents/MULTI_AGENT_RULES.md) for detailed collaborative rules and state flow constraints.\n$MARKER_END" >> "$AGENTS_FILE"
log_ok "Injected MAM guidelines pointer to existing AGENTS.md."
fi
fi
else
cp "$SRC_DIR/AGENTS.md" "$AGENTS_FILE"
log_ok "Guidelines AGENTS.md copied to project root."
fi
# 4. Gitignore adjustments
log_info "Registering runtime isolation blocks in .gitignore..."
GITIGNORE="$TARGET_DIR/.gitignore"
MAM_PATTERN="/.mam/"
VENV_PATTERN="/.venv/"
if [ -f "$GITIGNORE" ]; then
# Register .mam/ if absent
if grep -Eq '^/?\.mam/?$' "$GITIGNORE"; then
log_ok ".mam/ already registered in target's .gitignore."
else
echo -e "\n# Multi-Agent Mux (MAM) runtime databases and isolation cache\n$MAM_PATTERN" >> "$GITIGNORE"
log_ok "Appended /.mam/ registration to .gitignore."
fi
# Register .venv/ if absent
if grep -Eq '^/?\.venv/?$' "$GITIGNORE"; then
log_ok ".venv/ already registered in target's .gitignore."
else
echo -e "\n# Python virtual environment\n$VENV_PATTERN" >> "$GITIGNORE"
log_ok "Appended /.venv/ registration to .gitignore."
fi
else
echo -e "# Multi-Agent Mux (MAM) runtime databases and isolation cache\n$MAM_PATTERN\n\n# Python virtual environment\n$VENV_PATTERN" > "$GITIGNORE"
log_ok "Created .gitignore with MAM and .venv exclusions."
fi
# 5. Python Virtual Environment Setup (F-1)
log_info "Bootstrapping Python virtual environment (.venv) in target..."
VENV_NAME="$TARGET_DIR/.venv"
if [ ! -d "$VENV_NAME" ]; then
python3 -m venv "$VENV_NAME"
log_ok "Virtual environment created."
else
log_info "Virtual environment (.venv) already exists. Skipping creation."
fi
# Upgrade pip and install dependencies inside target venv
# shellcheck disable=SC1091
source "$VENV_NAME"/bin/activate
pip install --upgrade pip
REQ_FILE="$TARGET_DIR/.agents/skills/multi-agent-mux-delegate-job/requirements.txt"
if [ -f "$REQ_FILE" ]; then
log_info "Installing dependencies from $REQ_FILE..."
pip install -r "$REQ_FILE"
log_ok "Dependencies installed successfully."
else
log_warn "Could not find requirements file: $REQ_FILE. Installing defaults."
pip install "paho-mqtt>=2.0.0" pyyaml
fi
deactivate
# Done
log_ok "MAM Installation completed successfully!"
cat <<EOF
--------------------------------------------------------------------------------
💡 Quick Start Guide:
1. Initialize a new isolated session:
$ bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \\
--workspace "$TARGET_DIR" --agent claude --role developer --isolate \\
--herdr-server multi-agent-mux
2. Attach to the running session:
$ HERDR_SERVER_NAME=multi-agent-mux herdr agent attach <session_name>
3. Gracefully stop the session:
$ bash .agents/skills/multi-agent-mux-stop/scripts/stop_session.sh \\
--session <session_name> --agent claude
--------------------------------------------------------------------------------
EOF