swarm repositories / source
aboutsummaryrefslogtreecommitdiff
path: root/scripts/install-local.sh
blob: b60027e21fc43d0dadcd68358cabdb996d80a39c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SKILL_SOURCE_ROOT="${ROOT_DIR}/assets/codex-skills"
SYSTEMD_TEMPLATE_ROOT="${ROOT_DIR}/assets/systemd"
LOCAL_ROOT="${1:-$HOME/.local}"
SKILL_DEST_ROOT="${2:-$HOME/.codex/skills}"
LOCAL_BIN_DIR="${LOCAL_ROOT}/bin"
SYSTEMD_USER_DIR="${HOME}/.config/systemd/user"
UI_SERVICE_NAME="${FIDGET_SPINNER_UI_SERVICE_NAME:-fidget-spinner-libgrid-ui.service}"
UI_PROJECT_ROOT="${FIDGET_SPINNER_UI_PROJECT:-$HOME/programming/projects/libgrid/.worktrees/libgrid-lp-oracle-cutset}"
UI_BIND="${FIDGET_SPINNER_UI_BIND:-127.0.0.1:8913}"

escape_sed_replacement() {
  printf '%s' "$1" | sed -e 's/[\\/&]/\\&/g'
}

install_skill_link() {
  local name="$1"
  local source_dir="${SKILL_SOURCE_ROOT}/${name}"
  local dest_dir="${SKILL_DEST_ROOT}/${name}"
  mkdir -p "${SKILL_DEST_ROOT}"
  rm -rf "${dest_dir}"
  ln -s "${source_dir}" "${dest_dir}"
  printf 'installed skill symlink: %s -> %s\n' "${dest_dir}" "${source_dir}"
}

listener_pid_for_bind() {
  local bind="$1"
  local port="${bind##*:}"
  ss -ltnp "( sport = :${port} )" 2>/dev/null \
    | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' \
    | head -n 1
}

evict_conflicting_navigator() {
  local pid
  pid="$(listener_pid_for_bind "${UI_BIND}")"
  if [[ -z "${pid}" ]]; then
    return 0
  fi
  local cmd
  cmd="$(ps -p "${pid}" -o args= || true)"
  if [[ "${cmd}" == *"fidget-spinner-cli ui serve"* ]]; then
    kill "${pid}"
    for _ in {1..20}; do
      if ! kill -0 "${pid}" 2>/dev/null; then
        printf 'stopped conflicting navigator process: pid=%s\n' "${pid}"
        return 0
      fi
      sleep 0.1
    done
    printf 'failed to stop conflicting navigator process: pid=%s\n' "${pid}" >&2
    return 1
  fi
  printf 'refusing to steal %s from non-spinner process: %s\n' "${UI_BIND}" "${cmd}" >&2
  return 1
}

install_libgrid_ui_service() {
  if [[ ! -d "${UI_PROJECT_ROOT}" ]]; then
    printf 'libgrid navigator root does not exist: %s\n' "${UI_PROJECT_ROOT}" >&2
    return 1
  fi
  if ! command -v systemctl >/dev/null 2>&1; then
    printf 'systemctl unavailable; skipping navigator service install\n' >&2
    return 0
  fi

  local service_path="${SYSTEMD_USER_DIR}/${UI_SERVICE_NAME}"
  local template_path="${SYSTEMD_TEMPLATE_ROOT}/${UI_SERVICE_NAME}.in"
  mkdir -p "${SYSTEMD_USER_DIR}"
  sed \
    -e "s|@HOME@|$(escape_sed_replacement "${HOME}")|g" \
    -e "s|@LOCAL_BIN_DIR@|$(escape_sed_replacement "${LOCAL_BIN_DIR}")|g" \
    -e "s|@UI_PROJECT_ROOT@|$(escape_sed_replacement "${UI_PROJECT_ROOT}")|g" \
    -e "s|@UI_BIND@|$(escape_sed_replacement "${UI_BIND}")|g" \
    "${template_path}" > "${service_path}"
  chmod 0644 "${service_path}"
  printf 'installed user service: %s\n' "${service_path}"

  export XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
  if [[ -z "${DBUS_SESSION_BUS_ADDRESS:-}" && -S "${XDG_RUNTIME_DIR}/bus" ]]; then
    export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
  fi
  if ! systemctl --user daemon-reload; then
    printf 'systemd user manager unavailable; skipping navigator service activation\n' >&2
    return 0
  fi
  evict_conflicting_navigator
  if systemctl --user is-enabled --quiet "${UI_SERVICE_NAME}"; then
    systemctl --user restart "${UI_SERVICE_NAME}"
    printf 'restarted user service: %s\n' "${UI_SERVICE_NAME}"
  else
    systemctl --user enable --now "${UI_SERVICE_NAME}"
    printf 'enabled user service: %s\n' "${UI_SERVICE_NAME}"
  fi
}

mkdir -p "${LOCAL_BIN_DIR}"

cargo build --release -p fidget-spinner-cli --manifest-path "${ROOT_DIR}/Cargo.toml"
install -m 0755 \
  "${ROOT_DIR}/target/release/fidget-spinner-cli" \
  "${LOCAL_BIN_DIR}/fidget-spinner-cli"

printf 'installed binary: %s\n' "${LOCAL_BIN_DIR}/fidget-spinner-cli"

install_skill_link "fidget-spinner"
install_skill_link "frontier-loop"
install_libgrid_ui_service

printf 'mcp command: %s\n' "${LOCAL_BIN_DIR}/fidget-spinner-cli mcp serve"