Files
agenticCode/manage-ac.sh
Ingo Schnabel 0dfc85a11b Fixes
2026-07-19 10:34:15 +02:00

246 lines
8.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Manage the AgenticCode stack: build and (re)deploy ac-code-server + neo4j + ac-ui
# via docker-compose, and install the ac-cli launcher to the user's local bin.
#
# Run without arguments for the command list.
#
# Note: running this with no argument used to mean "deploy" (when the script was still
# called deploy.sh). It now prints help instead — a full deploy bumps the version and
# rebuilds everything, which is not something a bare, argument-less invocation should
# trigger by accident. Say 'deploy' when you mean it.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
CLI_INSTALL_DIR="$HOME/.local/share/agenticcode"
CLI_JAR_DEST="$CLI_INSTALL_DIR/ac-cli.jar"
CLI_BIN="$HOME/.local/bin/ac"
CLI_MARKER="# agenticcode-ac-cli-launcher"
log() { echo "==> $*"; }
compose() {
if docker compose version >/dev/null 2>&1; then
docker compose "$@"
else
docker-compose "$@"
fi
}
require_docker() {
if ! docker info >/dev/null 2>&1; then
echo "Docker does not appear to be running (or not reachable). Start Docker and re-run." >&2
exit 1
fi
}
# Stamps ac-cli's bundled version from ac-code-server's agenticcode.version (the single
# source of truth), so 'ac version' can detect a stale CLI against a newer server.
# Note: a full build already bumps agenticcode.version and stamps ac-cli via the
# ac-mvn-plugins 'bump-version' mojo (bound to ac-code-server's generate-resources phase).
# This function is only used by the CLI-only rebuild path, which must NOT bump but must
# still sync the CLI to the current server version.
stamp_cli_version() {
local props="ac-code-server/src/main/resources/application.properties"
local cli_props="ac-cli/src/main/resources/agenticcode.properties"
local current
current="$(grep -m1 '^agenticcode.version=' "$props" | cut -d= -f2)"
if [[ -z "$current" ]]; then
echo "Could not find agenticcode.version in $props" >&2
exit 1
fi
sed -i "s/^version=.*/version=$current/" "$cli_props"
log "Stamped ac-cli version: $current"
}
build_all() {
# The version bump + ac-cli stamp happen inside the Maven build (ac-mvn-plugins
# 'bump-version' mojo on ac-code-server), since 'install' is a trigger goal.
log "Building all modules (mvn clean install -DskipTests)"
mvn clean install -DskipTests
}
build_cli_only() {
stamp_cli_version
log "Building ac-cli (mvn -pl ac-cli -am package -DskipTests)"
mvn -pl ac-cli -am package -DskipTests
}
install_cli() {
local jar
jar="$(find ac-cli/target -maxdepth 1 -name 'ac-cli-*.jar' ! -name 'original-*' | head -n1)"
if [[ -z "$jar" ]]; then
echo "No ac-cli jar found in ac-cli/target — build failed?" >&2
exit 1
fi
mkdir -p "$CLI_INSTALL_DIR" "$HOME/.local/bin"
cp "$jar" "$CLI_JAR_DEST"
if [[ -e "$CLI_BIN" ]] && ! grep -q "$CLI_MARKER" "$CLI_BIN" 2>/dev/null; then
echo "Refusing to overwrite $CLI_BIN — it already exists and wasn't installed by this script." >&2
echo "Remove it manually first, or install elsewhere." >&2
exit 1
fi
cat > "$CLI_BIN" <<EOF
#!/usr/bin/env bash
$CLI_MARKER
exec java -jar "$CLI_JAR_DEST" "\$@"
EOF
chmod +x "$CLI_BIN"
log "Installed ac-cli -> $CLI_BIN (jar: $CLI_JAR_DEST)"
case ":$PATH:" in
*":$HOME/.local/bin:"*) ;;
*) echo "Note: $HOME/.local/bin is not on your PATH. Add it, e.g.: export PATH=\"\$HOME/.local/bin:\$PATH\"" ;;
esac
}
cmd_deploy() {
build_all
require_docker
log "Stopping ac-code-server container (neo4j left untouched)"
compose stop ac-code-server || true
compose rm -f ac-code-server || true
log "Building ac-code-server image"
compose build ac-code-server
log "Starting neo4j + ac-code-server"
compose up -d neo4j ac-code-server
deploy_ui
install_cli
}
# (Re)builds the ac-ui image (npm build runs inside Docker) and restarts its container.
deploy_ui() {
log "Building ac-ui image (npm build runs inside Docker)"
compose build ac-ui
log "Starting ac-ui (http://localhost:5174)"
compose up -d ac-ui
}
cmd_stop() {
require_docker
log "Stopping ac-code-server container only (neo4j left running)"
compose stop ac-code-server
}
cmd_cli() {
build_cli_only
install_cli
}
cmd_ui() {
require_docker
deploy_ui
}
cmd_logs() {
require_docker
if [[ "${1:-}" == "-f" ]]; then
docker logs -f --tail 200 agenticcode-server
else
docker logs --tail 200 agenticcode-server
fi
}
# Restarts the running ac-code-server container without rebuilding anything. Useful to
# abort a long server-side job (a deep refresh keeps running after its HTTP client is
# killed — the request is not the job) or to pick up a config change.
cmd_restart() {
require_docker
log "Restarting ac-code-server (no build; neo4j untouched)"
docker restart agenticcode-server
}
# Reports what is up and which version answers, without ever failing on a down stack —
# that is precisely the case it exists for. Every probe is guarded, since 'set -e' would
# otherwise abort this command exactly when it has something to report.
cmd_status() {
if ! docker info >/dev/null 2>&1; then
echo "Docker: not running (or not reachable)"
return 0
fi
log "Containers"
docker ps -a --filter "name=agenticcode-" \
--format ' {{.Names}}\t{{.Status}}' 2>/dev/null || true
log "Server"
local version
version="$(curl -fsS --max-time 3 http://localhost:8787/api/version 2>/dev/null || true)"
if [[ -n "$version" ]]; then
echo " http://localhost:8787 -> $version"
else
echo " http://localhost:8787 -> unreachable"
fi
log "Projects"
local projects
projects="$(curl -fsS --max-time 3 http://localhost:8787/api/projects 2>/dev/null || true)"
if [[ -n "$projects" ]]; then
echo "$projects" | grep -o '"name":"[^"]*"' | cut -d'"' -f4 | sed 's/^/ /' || echo " (none)"
else
echo " (server unreachable)"
fi
}
# Stops the whole stack, neo4j included — 'stop' deliberately leaves neo4j up, so this is
# the only scripted way to bring everything down.
#
# Intentionally NOT 'compose down -v': the neo4j-data volume holds the ingested graph
# (hundreds of thousands of nodes, hours of ingest). 'down' means "stack off", never
# "graph gone". Do not add -v here.
cmd_down() {
require_docker
log "Stopping the whole stack (neo4j included; the graph volume is kept)"
compose down
}
usage() {
cat <<'EOF'
manage-ac.sh — manage the AgenticCode stack
Usage: ./manage-ac.sh <command>
deploy Full deploy: bump version, mvn clean install, rebuild+restart
ac-code-server, rebuild+start ac-ui, install ac-cli.
(neo4j is left running untouched if already up)
restart Restart ac-code-server only — no build. Also aborts a long
server-side job such as a running deep refresh.
stop Stop ac-code-server only; neo4j and ac-ui keep running.
down Stop the whole stack, neo4j included. The graph volume is kept.
status Show containers, the server version and the ingested projects.
Works (and reports) when the stack is down.
cli Build and (re)install ac-cli only — no Docker involved.
ui Rebuild and restart ac-ui only (npm build runs inside Docker;
no local Node needed). Served at http://localhost:5174.
logs [-f] Last 200 lines of ac-code-server logs; -f to follow.
Notes:
- The server answers on http://localhost:8787, the UI on http://localhost:5174.
- The version bump lives in the Maven build (ac-mvn-plugins 'bump-version' mojo):
every 'mvn package'/'install'/'deploy' bumps agenticcode.version and stamps ac-cli.
'mvn test'/'compile'/'quarkus:dev' do not. 'deploy' bumps because it runs a full
install — which is why a bare, argument-less invocation means help, not deploy.
EOF
}
case "${1:-}" in
deploy) cmd_deploy ;;
restart) cmd_restart ;;
stop) cmd_stop ;;
down) cmd_down ;;
status) cmd_status ;;
cli) cmd_cli ;;
ui) cmd_ui ;;
logs) shift; cmd_logs "${1:-}" ;;
"" | -h | --help | help) usage ;;
*)
echo "Unknown command: $1" >&2
echo >&2
usage >&2
exit 1
;;
esac