From 5ad521ad4c053cebddad0da9b14bcf8f88b82b43 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Mon, 1 Jun 2026 01:46:53 -0700 Subject: [PATCH] feat(tracker-web): macOS LaunchAgent keep-alive for the fleet web tracker Adds dashboards/tracker-web/launchd/ (boot script + install.sh + README) so tracker-web (:3003) auto-starts on login and restarts on crash/reboot, instead of dying silently between sessions. Mirrors agent-queue/launchd: boot script repairs PATH, loads JWT_SECRET from platform-service/.env (+ ~/.tracker-web.env overrides), points at the local platform-service, and execs `pnpm dev`. plist uses unconditional KeepAlive (restart on any exit, incl. a clean SIGTERM) + a 10s throttle; install.sh frees :3003 first to avoid a clash with deploy-gigafactory. Verified: killing the process respawns it and :3003 returns. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- dashboards/tracker-web/launchd/README.md | 37 ++++++ dashboards/tracker-web/launchd/install.sh | 110 ++++++++++++++++++ .../tracker-web/launchd/tracker-web-boot.sh | 44 +++++++ 3 files changed, 191 insertions(+) create mode 100644 dashboards/tracker-web/launchd/README.md create mode 100755 dashboards/tracker-web/launchd/install.sh create mode 100755 dashboards/tracker-web/launchd/tracker-web-boot.sh diff --git a/dashboards/tracker-web/launchd/README.md b/dashboards/tracker-web/launchd/README.md new file mode 100644 index 00000000..f8aa6793 --- /dev/null +++ b/dashboards/tracker-web/launchd/README.md @@ -0,0 +1,37 @@ +# tracker-web LaunchAgent (keep-alive on :3003) + +Auto-starts the fleet **web tracker** (`tracker-web`) on login and restarts it on +crash/reboot, so `http://localhost:3003` stays up without a babysitter. Mirrors +the `agent-queue/launchd/` pattern in `learning_ai_devops_tools`. + +## Files + +- `tracker-web-boot.sh` — boot entrypoint: repairs `PATH`, loads `JWT_SECRET` (+ + co.) from `../../services/platform-service/.env` and optional + `~/.tracker-web.env` overrides, points the app at the local platform-service + (`PLATFORM_API_URL`, default `http://localhost:4003`), then `exec pnpm dev`. +- `install.sh` — renders `~/Library/LaunchAgents/com.bytelyst.tracker-web.plist` + (`RunAtLoad` + unconditional `KeepAlive` so it restarts on any exit, incl. a + clean SIGTERM, + a 10s crash-loop throttle), frees `:3003` if something else is + on it, then bootstraps + kickstarts it. + +## Use + +```bash +bash launchd/install.sh # install + start +bash launchd/install.sh --uninstall # stop + remove + +tail -f ~/Library/Logs/tracker-web/tracker-web.out.log # logs +launchctl print gui/$(id -u)/com.bytelyst.tracker-web | sed -n '1,20p' # status +``` + +## Notes + +- **Prereqs:** the platform-service backend on `:4003` (see + `learning_ai_devops_tools/scripts/deploy-gigafactory.sh`) and `pnpm` on `PATH`. +- **Don't double-manage the port:** while this LaunchAgent owns `:3003`, do not + also run `deploy-gigafactory.sh --with-tracker` / `--tracker-only` — they would + clash on `:3003`. Use one or the other. +- **Per-machine overrides:** drop env in `~/.tracker-web.env` (not tracked) to + override `PLATFORM_API_URL`, `DEFAULT_PRODUCT_ID`, etc. +- macOS only (LaunchAgents). On Linux use a `systemd --user` unit. diff --git a/dashboards/tracker-web/launchd/install.sh b/dashboards/tracker-web/launchd/install.sh new file mode 100755 index 00000000..52608a32 --- /dev/null +++ b/dashboards/tracker-web/launchd/install.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# +# install.sh — install (or remove) the macOS LaunchAgent that auto-starts +# tracker-web (the fleet web tracker, :3003) on login and keeps it alive across +# reboot/crash. +# +# bash launchd/install.sh # render plist, load, and start now +# bash launchd/install.sh --uninstall # stop, unload, and remove the plist +# +# The plist is generated from the resolved repo path so it works on any clone. +# Logs land in ~/Library/Logs/tracker-web/. +# +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)" +WEB_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd -P)" +WRAPPER="$SCRIPT_DIR/tracker-web-boot.sh" + +LABEL="com.bytelyst.tracker-web" +PLIST="$HOME/Library/LaunchAgents/$LABEL.plist" +LOG_DIR="$HOME/Library/Logs/tracker-web" +UID_NUM="$(id -u)" +DOMAIN="gui/$UID_NUM" + +if [ "$(uname -s)" != "Darwin" ]; then + echo "install.sh: macOS only (LaunchAgents). On Linux use a systemd --user unit." >&2 + exit 1 +fi + +uninstall() { + echo "[launchd] booting out $LABEL ..." + launchctl bootout "$DOMAIN/$LABEL" 2>/dev/null || true + rm -f "$PLIST" + echo "[launchd] removed $PLIST (tracker-web stopped)" +} + +if [ "${1:-}" = "--uninstall" ] || [ "${1:-}" = "-u" ]; then + uninstall + exit 0 +fi + +[ -f "$WRAPPER" ] || { echo "install.sh: missing $WRAPPER" >&2; exit 1; } +chmod +x "$WRAPPER" 2>/dev/null || true +mkdir -p "$HOME/Library/LaunchAgents" "$LOG_DIR" + +# Avoid a port clash: if something else is already serving :3003 (e.g. a +# deploy-gigafactory.sh --tracker-only run), stop it so launchd owns the port. +if lsof -ti tcp:3003 >/dev/null 2>&1; then + echo "[launchd] freeing :3003 (an existing tracker is running) ..." + lsof -ti tcp:3003 | xargs kill 2>/dev/null || true + sleep 2 +fi + +echo "[launchd] writing $PLIST" +cat > "$PLIST" < + + + + Label + $LABEL + + ProgramArguments + + /bin/bash + $WRAPPER + + + + RunAtLoad + + KeepAlive + + + ThrottleInterval + 10 + + WorkingDirectory + $WEB_DIR + + StandardOutPath + $LOG_DIR/tracker-web.out.log + StandardErrorPath + $LOG_DIR/tracker-web.err.log + + + EnvironmentVariables + + PATH + $HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + + + +EOF + +# Reload cleanly (bootout first so a re-run picks up plist changes). +launchctl bootout "$DOMAIN/$LABEL" 2>/dev/null || true +launchctl bootstrap "$DOMAIN" "$PLIST" +launchctl enable "$DOMAIN/$LABEL" +launchctl kickstart -k "$DOMAIN/$LABEL" + +echo "[launchd] installed + started: $LABEL (http://localhost:3003)" +echo "[launchd] status : launchctl print $DOMAIN/$LABEL | sed -n '1,20p'" +echo "[launchd] logs : tail -f $LOG_DIR/tracker-web.out.log" +echo "[launchd] stop : bash $SCRIPT_DIR/install.sh --uninstall" +echo +echo "NOTE: while this LaunchAgent owns :3003, do NOT also run" +echo " deploy-gigafactory.sh --with-tracker (it would clash on the port)." diff --git a/dashboards/tracker-web/launchd/tracker-web-boot.sh b/dashboards/tracker-web/launchd/tracker-web-boot.sh new file mode 100755 index 00000000..35068191 --- /dev/null +++ b/dashboards/tracker-web/launchd/tracker-web-boot.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# +# tracker-web-boot.sh — boot/login entrypoint for the fleet web tracker. +# +# Launched by the macOS LaunchAgent (see ./install.sh) so tracker-web auto-starts +# on login and survives crash/reboot via KeepAlive — the supervision a bare +# `next dev` (or deploy-gigafactory.sh --tracker-only) doesn't provide. +# +# It does what launchd's minimal environment needs: +# 1. Repairs PATH so node/pnpm are found. +# 2. Loads JWT_SECRET + co. from platform-service/.env (and optional +# ~/.tracker-web.env overrides) so the telemetry/health proxies work. +# 3. Points the app at the local platform-service and execs `next dev`. +# +set -uo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd -P)" +WEB_DIR="$(cd -- "$SCRIPT_DIR/.." >/dev/null 2>&1 && pwd -P)" # dashboards/tracker-web +PS_ENV="$(cd -- "$WEB_DIR/../../services/platform-service" >/dev/null 2>&1 && pwd -P)/.env" + +# launchd hands processes a bare PATH — prepend the usual node/pnpm locations. +export PATH="$HOME/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:${PATH:-}" + +# Backend secret + any other shared config from platform-service/.env, then +# per-machine overrides (~/.tracker-web.env, NOT tracked) which win. +set -a +[ -f "$PS_ENV" ] && . "$PS_ENV" +[ -f "$HOME/.tracker-web.env" ] && . "$HOME/.tracker-web.env" +set +a + +# Where the app reaches the fleet backend + which product it scopes to by default. +: "${PLATFORM_API_URL:=http://localhost:4003}" +: "${PLATFORM_SERVICE_URL:=$PLATFORM_API_URL}" +: "${DEFAULT_PRODUCT_ID:=lysnrai}" +: "${PRODUCT_ID:=$DEFAULT_PRODUCT_ID}" +export PLATFORM_API_URL PLATFORM_SERVICE_URL DEFAULT_PRODUCT_ID PRODUCT_ID + +echo "[tracker-web-boot] $(date '+%Y-%m-%d %H:%M:%S') starting tracker-web on :3003" \ + "(platform=$PLATFORM_API_URL, product=$DEFAULT_PRODUCT_ID)" + +cd "$WEB_DIR" +# exec so the LaunchAgent tracks the real next-dev PID (clean KeepAlive restarts). +# `dev` matches the rest of the local setup; the package script pins --port 3003. +exec pnpm dev