107 lines
4.4 KiB
Bash
Executable File
107 lines
4.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Install Panama's searchable launcher actions as one narrow directory link.
|
|
# Keeping the runtime path stable lets Vicinae watch it while every command
|
|
# remains authored and reviewed in the Panama repository.
|
|
|
|
set -euo pipefail
|
|
|
|
panama_path="${PANAMA_PATH:-$HOME/.local/share/Panama}"
|
|
vicinae_data_dir="${VICINAE_DATA_DIR:-$HOME/.local/share/vicinae}"
|
|
source_dir="$panama_path/config/local/share/vicinae/scripts"
|
|
scripts_dir="$vicinae_data_dir/scripts"
|
|
target_dir="$scripts_dir/panama"
|
|
backup_root="$vicinae_data_dir/backups"
|
|
backup_dir="$backup_root/panama.pre-panama"
|
|
legacy_backup="$scripts_dir/panama.pre-panama"
|
|
|
|
[[ -d "$source_dir" ]] || {
|
|
printf 'Panama command source is missing: %s\n' "$source_dir" >&2
|
|
exit 1
|
|
}
|
|
|
|
mkdir -p "$scripts_dir" "$backup_root"
|
|
|
|
# Older Panama builds preserved this directory alongside searchable commands.
|
|
# Move it out before reloading so those scripts cannot appear twice.
|
|
if [[ -e "$legacy_backup" ]]; then
|
|
if [[ -e "$backup_dir" ]]; then
|
|
printf 'Refusing to move %s; backup already exists at %s\n' \
|
|
"$legacy_backup" "$backup_dir" >&2
|
|
exit 1
|
|
fi
|
|
mv "$legacy_backup" "$backup_dir"
|
|
fi
|
|
|
|
if [[ -L "$target_dir" ]]; then
|
|
rm "$target_dir"
|
|
elif [[ -e "$target_dir" ]]; then
|
|
if [[ -e "$backup_dir" ]]; then
|
|
printf 'Refusing to replace %s; backup already exists at %s\n' \
|
|
"$target_dir" "$backup_dir" >&2
|
|
exit 1
|
|
fi
|
|
mv "$target_dir" "$backup_dir"
|
|
fi
|
|
|
|
ln -s "$source_dir" "$target_dir"
|
|
|
|
# ── Extensions ───────────────────────────────────────────────────────────────
|
|
#
|
|
# Script commands are a file and a shebang, so they are linked. Extensions are
|
|
# not: they are TypeScript that has to be compiled, and `vici build` writes its
|
|
# output straight into Vicinae's data directory rather than leaving a bundle to
|
|
# link. So the source lives in this repository and the build is what installs
|
|
# it.
|
|
#
|
|
# Never fatal, and never a reason to fail a stage. A build wants npm and the
|
|
# network, and neither is guaranteed at this point in an install -- npm arrives
|
|
# with nvm earlier in install-packages, which can itself be skipped. An
|
|
# extension that did not build is a launcher missing one command, not a desktop
|
|
# that failed to install.
|
|
extensions_source="$panama_path/config/local/share/vicinae/extensions"
|
|
|
|
# npm comes from nvm, and nvm is a shell function in a file that only an
|
|
# interactive shell sources. A stage is not one, so without this npm is simply
|
|
# absent and the build below is skipped -- silently, which is the whole problem.
|
|
#
|
|
# This machine hid the bug: /usr/sbin/npm existed, but only because Claude
|
|
# Desktop depends on nodejs and dragged it in. A machine without that would have
|
|
# installed the launcher and quietly not built its search extension.
|
|
if [[ -s /etc/profile.d/nvm.sh ]] && ! command -v npm >/dev/null 2>&1; then
|
|
# nvm's script reads unset variables, which `set -u` treats as fatal.
|
|
set +u
|
|
# shellcheck source=/dev/null
|
|
source /etc/profile.d/nvm.sh
|
|
set -u
|
|
fi
|
|
|
|
if [[ -d "$extensions_source" ]] && command -v npm >/dev/null 2>&1; then
|
|
for extension in "$extensions_source"/*/; do
|
|
[[ -f "$extension/package.json" ]] || continue
|
|
name="$(basename "$extension")"
|
|
|
|
# Skip a build that would produce what is already there. `npm ci`
|
|
# alone takes long enough to be worth not repeating on every re-run of
|
|
# a stage that is otherwise nearly instant.
|
|
built="$vicinae_data_dir/extensions/$name"
|
|
if [[ -d "$built" && "$extension/src" -ot "$built" ]]; then
|
|
printf 'Vicinae extension %s is already built\n' "$name"
|
|
continue
|
|
fi
|
|
|
|
printf 'Building Vicinae extension %s\n' "$name"
|
|
if ! (cd "$extension" && npm ci --silent >/dev/null 2>&1 && npm run build >/dev/null 2>&1); then
|
|
printf 'Vicinae extension %s did not build; skipping\n' "$name" >&2
|
|
fi
|
|
done
|
|
elif [[ -d "$extensions_source" ]]; then
|
|
printf 'npm is not available, so Vicinae extensions were not built\n' >&2
|
|
fi
|
|
|
|
# The server also rescans periodically, but an explicit reload makes a setup
|
|
# run deterministic. If Vicinae is not active yet, its startup scan is enough.
|
|
if command -v vicinae >/dev/null 2>&1 && vicinae ping >/dev/null 2>&1; then
|
|
vicinae cmd launch core:reload-scripts >/dev/null 2>&1 || true
|
|
fi
|