mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
310 lines
12 KiB
Bash
Executable File
310 lines
12 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Legacy AgentOps multi-runtime plugin installer.
|
|
# New installs should clone the repository and run `ao skills link` instead.
|
|
# Usage: bash <(curl -fsSL https://raw.githubusercontent.com/boshu2/agentops/main/scripts/install.sh)
|
|
# bash scripts/install.sh --dev
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage:
|
|
bash scripts/install.sh
|
|
bash scripts/install.sh --dev
|
|
bash scripts/install.sh --with-hooks
|
|
bash scripts/install.sh --tier spine
|
|
|
|
Options:
|
|
--dev Configure this checkout for AgentOps development: install repo
|
|
hooks, build cli/bin/ao, and smoke-test pre-push wiring.
|
|
--with-hooks
|
|
Also install runtime hooks. Default install is hookless.
|
|
--tier <spine|all>
|
|
Which skill tier to install. "spine" installs only the
|
|
metadata-derived core (`disposition: keep`),
|
|
skipping the experimental corpus/flywheel tier; "all" (default)
|
|
installs the whole bundle. Filters the Codex/AGY bundle installs;
|
|
the Claude plugin path is whole-bundle (manifest split is future work).
|
|
-h, --help Show this help.
|
|
|
|
Deprecated:
|
|
This 3.x compatibility installer is retained for one migration release. New
|
|
installs should use one canonical checkout plus `ao skills link`.
|
|
EOF
|
|
}
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
WITH_HOOKS="${AGENTOPS_INSTALL_HOOKS:-0}"
|
|
TIER="${AGENTOPS_INSTALL_TIER:-all}"
|
|
# Offline/local-source mode: install from an already-extracted checkout instead
|
|
# of downloading from GitHub. Shared with install-codex.sh / install-agy.sh /
|
|
# install-opencode.sh so tests (and air-gapped installs) run against the
|
|
# worktree. Local-source mode installs the full bundle (no spine pruning, which
|
|
# would mutate the source checkout).
|
|
SOURCE_ROOT_OVERRIDE="${AGENTOPS_BUNDLE_ROOT:-}"
|
|
|
|
# prune_bundle_to_spine removes every non-core skill dir from an extracted
|
|
# AgentOps bundle so the legacy --tier spine spelling ships only the four
|
|
# load-bearing skills. The selection comes from generated skill metadata.
|
|
prune_bundle_to_spine() {
|
|
local bundle="$1"
|
|
local selector="$bundle/scripts/select-spine-skills.sh"
|
|
if [[ ! -f "$selector" ]]; then
|
|
echo "Warning: spine selector missing ($selector); installing all skills." >&2
|
|
return 0
|
|
fi
|
|
local keep
|
|
keep="$(bash "$selector" "$bundle/skills" 2>/dev/null || true)"
|
|
if [[ -z "$keep" ]]; then
|
|
echo "Warning: no spine skills resolved; installing all skills." >&2
|
|
return 0
|
|
fi
|
|
local skills_root dir name
|
|
for skills_root in "$bundle/skills" "$bundle/skills-codex"; do
|
|
[[ -d "$skills_root" ]] || continue
|
|
for dir in "$skills_root"/*/; do
|
|
[[ -d "$dir" ]] || continue
|
|
name="$(basename "$dir")"
|
|
if ! grep -qxF "$name" <<<"$keep"; then
|
|
rm -rf "$dir"
|
|
fi
|
|
done
|
|
done
|
|
echo "Tier spine (core): kept $(printf '%s\n' "$keep" | grep -c .) metadata-selected core skills."
|
|
}
|
|
|
|
install_dev() {
|
|
local repo_root
|
|
repo_root="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
if [[ ! -d "$repo_root/cli" ]]; then
|
|
echo "Error: --dev must be run from an AgentOps source checkout." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Building the AgentOps development CLI..."
|
|
make -C "$repo_root/cli" build
|
|
|
|
echo ""
|
|
echo "Done! Development checkout ready."
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--dev)
|
|
shift
|
|
if [[ $# -gt 0 ]]; then
|
|
echo "Unknown option for --dev: $1" >&2
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
install_dev
|
|
exit 0
|
|
;;
|
|
--with-hooks)
|
|
WITH_HOOKS=1
|
|
shift
|
|
;;
|
|
--no-hooks)
|
|
WITH_HOOKS=0
|
|
shift
|
|
;;
|
|
--tier)
|
|
shift
|
|
TIER="${1:-}"
|
|
shift || true
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1" >&2
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
WITH_HOOKS_NORMALIZED="$(printf '%s' "$WITH_HOOKS" | tr '[:upper:]' '[:lower:]')"
|
|
case "$WITH_HOOKS_NORMALIZED" in
|
|
1|true|yes|on)
|
|
WITH_HOOKS=1
|
|
;;
|
|
0|false|no|off|"")
|
|
WITH_HOOKS=0
|
|
;;
|
|
*)
|
|
echo "Invalid AGENTOPS_INSTALL_HOOKS/--with-hooks value: $WITH_HOOKS" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
case "$TIER" in
|
|
spine|all) ;;
|
|
*)
|
|
echo "Invalid --tier/AGENTOPS_INSTALL_TIER value: $TIER (want: spine|all)" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
|
|
echo "Installing AgentOps..."
|
|
|
|
# Check prerequisites
|
|
command -v curl >/dev/null 2>&1 || { echo "Error: curl required."; exit 1; }
|
|
|
|
# Per-runtime detection (soc-vuu6.31). The old `claude || codex` test bounced
|
|
# only on zero runtimes — single-runtime users got the README mixed-model
|
|
# example silently. Detect each runtime explicitly so we can: (a) report
|
|
# yes/no per runtime, (b) name the mode AgentOps will operate in, and
|
|
# (c) point single-runtime users at the install link for the other.
|
|
HAS_CLAUDE=no
|
|
HAS_CODEX=no
|
|
HAS_AGY=no
|
|
command -v claude >/dev/null 2>&1 && HAS_CLAUDE=yes
|
|
command -v codex >/dev/null 2>&1 && HAS_CODEX=yes
|
|
command -v agy >/dev/null 2>&1 && HAS_AGY=yes
|
|
echo "Detected Claude Code: $HAS_CLAUDE. Detected Codex CLI: $HAS_CODEX. Detected Gemini/AGY: $HAS_AGY."
|
|
|
|
# Count distinct runtimes so we can name single- vs mixed-model mode across all
|
|
# three supported vendors (Claude, Codex, Gemini/AGY) — not just claude/codex.
|
|
RUNTIME_COUNT=0
|
|
[ "$HAS_CLAUDE" = "yes" ] && RUNTIME_COUNT=$((RUNTIME_COUNT + 1))
|
|
[ "$HAS_CODEX" = "yes" ] && RUNTIME_COUNT=$((RUNTIME_COUNT + 1))
|
|
[ "$HAS_AGY" = "yes" ] && RUNTIME_COUNT=$((RUNTIME_COUNT + 1))
|
|
|
|
if [ "$RUNTIME_COUNT" -ge 2 ]; then
|
|
echo "AgentOps will use mixed-model mode (cross-vendor council, parallel /rpi)."
|
|
elif [ "$RUNTIME_COUNT" -eq 1 ]; then
|
|
if [ "$HAS_CLAUDE" = "yes" ]; then
|
|
echo "AgentOps will use single-runtime mode (Claude Code only)."
|
|
elif [ "$HAS_CODEX" = "yes" ]; then
|
|
echo "AgentOps will use single-runtime mode (Codex CLI only)."
|
|
else
|
|
echo "AgentOps will use single-runtime mode (Gemini/AGY only)."
|
|
fi
|
|
echo "To unlock mixed-model judging, install another runtime:"
|
|
[ "$HAS_CLAUDE" = "no" ] && echo " Claude Code: https://docs.anthropic.com/en/docs/claude-code"
|
|
[ "$HAS_CODEX" = "no" ] && echo " Codex CLI: https://github.com/openai/codex"
|
|
[ "$HAS_AGY" = "no" ] && echo " Gemini/AGY: https://antigravity.google"
|
|
else
|
|
echo "Warning: No supported coding agent found (claude, codex, agy)."
|
|
echo "AgentOps requires Claude Code, Codex CLI, or Gemini/AGY. Install one first:"
|
|
echo " Claude Code: https://docs.anthropic.com/en/docs/claude-code"
|
|
echo " Codex CLI: https://github.com/openai/codex"
|
|
echo " Gemini/AGY: https://antigravity.google"
|
|
echo "Continuing anyway — you can install an agent later."
|
|
fi
|
|
|
|
# Step 1: Install Codex plugin
|
|
echo "Step 1/3: Installing Codex plugin..."
|
|
if [ -n "$SOURCE_ROOT_OVERRIDE" ]; then
|
|
[ -f "$SOURCE_ROOT_OVERRIDE/scripts/install-codex.sh" ] \
|
|
|| { echo "Error: AGENTOPS_BUNDLE_ROOT missing scripts/install-codex.sh: $SOURCE_ROOT_OVERRIDE" >&2; exit 1; }
|
|
BUNDLE="$SOURCE_ROOT_OVERRIDE"
|
|
echo "Local-source mode: installing from $BUNDLE (full bundle; spine pruning skipped)."
|
|
else
|
|
TMP=$(mktemp -d)
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
curl -fsSL https://codeload.github.com/boshu2/agentops/tar.gz/refs/heads/main \
|
|
| tar xz -C "$TMP" --strip-components=1
|
|
BUNDLE="$TMP"
|
|
if [[ "$TIER" == "spine" ]]; then
|
|
echo "Tier: spine (core) — pruning bundle to metadata-selected core skills..."
|
|
prune_bundle_to_spine "$BUNDLE"
|
|
fi
|
|
fi
|
|
|
|
if command -v codex >/dev/null 2>&1; then
|
|
codex_args=()
|
|
if [[ "$WITH_HOOKS" == "1" ]]; then
|
|
codex_args+=(--with-hooks)
|
|
fi
|
|
# Expand-only-if-set: an empty array under `set -u` is an unbound-variable
|
|
# error on macOS bash 3.2, which is reachable now that local-source mode
|
|
# exercises this path offline.
|
|
AGENTOPS_BUNDLE_ROOT="$BUNDLE" bash "$BUNDLE/scripts/install-codex.sh" ${codex_args[@]+"${codex_args[@]}"}
|
|
else
|
|
echo "Codex CLI not found. Skipping Codex plugin install."
|
|
echo "For Claude Code, install skills via the plugin system:"
|
|
echo " npx skills@latest add boshu2/agentops --all -g"
|
|
fi
|
|
|
|
# Gemini/AGY plugin (reuses the already-extracted bundle in $TMP). jq is required
|
|
# by install-agy.sh; skip with a pointer if it is missing rather than aborting the
|
|
# whole install for Claude/Codex users.
|
|
if command -v agy >/dev/null 2>&1; then
|
|
if command -v jq >/dev/null 2>&1; then
|
|
echo "Installing Gemini/AGY plugin..."
|
|
AGENTOPS_BUNDLE_ROOT="$BUNDLE" bash "$BUNDLE/scripts/install-agy.sh"
|
|
else
|
|
echo "Gemini/AGY detected but 'jq' is missing. Install jq, then run:"
|
|
echo " curl -fsSL https://raw.githubusercontent.com/boshu2/agentops/main/scripts/install-agy.sh | bash"
|
|
fi
|
|
fi
|
|
|
|
# Step 2: Install CLI (optional — enhances with knowledge flywheel)
|
|
if command -v brew >/dev/null 2>&1; then
|
|
echo "Step 2/3: Installing CLI via Homebrew..."
|
|
if ! brew tap boshu2/agentops https://github.com/boshu2/homebrew-agentops; then
|
|
echo "Error: failed to add Homebrew tap boshu2/agentops." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! brew install agentops; then
|
|
echo "brew install agentops failed; trying brew upgrade agentops..."
|
|
if ! brew upgrade agentops; then
|
|
echo "Error: Homebrew could not install or upgrade agentops." >&2
|
|
echo "Try manually:" >&2
|
|
echo " brew update && brew upgrade agentops" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Step 3: Runtime-specific setup
|
|
if command -v ao >/dev/null 2>&1; then
|
|
echo "Note: To create repo-local .agents/ scaffolding, run 'ao init' from your repo root."
|
|
if [[ "$WITH_HOOKS" == "1" ]]; then
|
|
echo "Step 3/3: Runtime-specific hook setup is delegated to each runtime installer."
|
|
else
|
|
echo "Step 3/3: Hooks skipped (hookless default)."
|
|
echo "Optional: rerun with --with-hooks for runtimes that expose native hooks."
|
|
fi
|
|
|
|
# Optional health check
|
|
ao doctor 2>/dev/null && echo "Health check: PASS" || echo "Health check: run 'ao doctor' after setup"
|
|
fi
|
|
else
|
|
echo "Step 2/3: Skipping CLI (Homebrew not found). Install manually:"
|
|
echo " brew tap boshu2/agentops https://github.com/boshu2/homebrew-agentops"
|
|
echo " brew install agentops"
|
|
echo "Step 3/3: Runtime-specific setup complete."
|
|
fi
|
|
|
|
# Self-test: verify install.sh's aggregate claim before printing "Done"
|
|
# (age-txfnl). The per-runtime installers self-test and abort on failure, so
|
|
# reaching here already implies each ran clean; this tail is the orchestrator's
|
|
# own belt-and-suspenders check that the runtime we detected actually landed a
|
|
# config-enable entry + install metadata, so we never print "Done" over a
|
|
# half-installed state.
|
|
selftest_problems=0
|
|
if [ "$HAS_CODEX" = "yes" ]; then
|
|
codex_meta="${HOME}/.codex/.agentops-codex-install.json"
|
|
codex_cfg="${HOME}/.codex/config.toml"
|
|
if [ ! -f "$codex_meta" ]; then
|
|
echo "self-test: Codex install metadata missing ($codex_meta)" >&2
|
|
selftest_problems=$((selftest_problems + 1))
|
|
fi
|
|
if ! grep -qF 'agentops@agentops-marketplace' "$codex_cfg" 2>/dev/null; then
|
|
echo "self-test: Codex config missing plugin enable entry ($codex_cfg)" >&2
|
|
selftest_problems=$((selftest_problems + 1))
|
|
fi
|
|
fi
|
|
if [ "$selftest_problems" -gt 0 ]; then
|
|
echo "Error: install self-test failed with $selftest_problems problem(s); not all runtimes installed cleanly. Re-run this installer or run 'ao doctor' for details." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "Done! Verify it worked: start your coding agent and type /plan (or /quickstart)."
|