diff --git a/.gitignore b/.gitignore index 6d87318e3..119ae94d1 100644 --- a/.gitignore +++ b/.gitignore @@ -136,3 +136,4 @@ RELEASE_v*.md # Desktop demo-run scratch output (hermes writes demo/*.txt during recorded # walkthroughs). Throwaway artifacts, never part of the app. apps/desktop/demo/ +ui-tui/node.core diff --git a/packaging/freebsd/hermes_dashboard.in b/packaging/freebsd/hermes_dashboard.in new file mode 100644 index 000000000..a15acb385 --- /dev/null +++ b/packaging/freebsd/hermes_dashboard.in @@ -0,0 +1,135 @@ +#!/bin/sh +# +# Hermes Agent Dashboard — FreeBSD rc.d service +# +# Hermes dashboard web UI runs in the FOREGROUND. rc.d runs it under +# daemon(8), which backgrounds it, writes a pidfile, restarts on crash, +# drops privileges to the configured user, and redirects stdout/stderr +# to a logfile. +# +# Setup (one-time, as root): +# cp /home/clawdie/ai/hermes-bsd/packaging/freebsd/hermes_dashboard.in \ +# /usr/local/etc/rc.d/hermes_dashboard +# chmod 555 /usr/local/etc/rc.d/hermes_dashboard +# sysrc hermes_dashboard_enable=YES +# +# Requires: +# - hermes gateway already installed and configured +# - web UI built (cd ~/ai/hermes-bsd/web && npm run build) +# - hermes_daemon rc.d service (for shared run/log dirs) + +# PROVIDE: hermes_dashboard +# REQUIRE: LOGIN cleanvar hermes_daemon +# KEYWORD: shutdown + +. /etc/rc.subr + +name="hermes_dashboard" +rcvar="hermes_dashboard_enable" + +load_rc_config $name + +: ${hermes_dashboard_enable:="NO"} +: ${hermes_dashboard_user:="clawdie"} +: ${hermes_dashboard_group:="clawdie"} +: ${hermes_dashboard_program:="/home/clawdie/ai/hermes-bsd/venv/bin/hermes"} +: ${hermes_dashboard_home:="/home/clawdie/.hermes"} +: ${hermes_dashboard_run_dir:="/var/run/hermes"} +: ${hermes_dashboard_logfile:="/var/log/hermes/dashboard.log"} +: ${hermes_dashboard_host:="0.0.0.0"} +: ${hermes_dashboard_port:="9119"} + +pidfile="${hermes_dashboard_run_dir}/hermes-dashboard.pid" +supervisor_pidfile="${hermes_dashboard_run_dir}/hermes-dashboard-supervisor.pid" + +command="/usr/sbin/daemon" +procname="hermes" + +start_cmd="hermes_dashboard_start" +start_precmd="hermes_dashboard_prestart" +status_cmd="hermes_dashboard_status" +stop_cmd="hermes_dashboard_stop" +extra_commands="health" + +hermes_dashboard_prestart() +{ + install -d -o "${hermes_dashboard_user}" -g "${hermes_dashboard_group}" -m 0750 \ + "${hermes_dashboard_run_dir}" + install -d -o "${hermes_dashboard_user}" -g "${hermes_dashboard_group}" -m 0750 \ + "$(/usr/bin/dirname "${hermes_dashboard_logfile}")" + + export HERMES_HOME="${hermes_dashboard_home}" + + # Verify web UI is built before starting. + if [ ! -f "${hermes_dashboard_home}/../ai/hermes-bsd/hermes_cli/web_dist/index.html" ]; then + echo "ERROR: web_dist not found — build first: cd ~/ai/hermes-bsd/web && npm run build" + return 1 + fi +} + +hermes_dashboard_start() +{ + env HERMES_HOME="${hermes_dashboard_home}" \ + /usr/sbin/daemon \ + -P "${supervisor_pidfile}" \ + -p "${pidfile}" \ + -r \ + -t "${name}" \ + -u "${hermes_dashboard_user}" \ + -o "${hermes_dashboard_logfile}" \ + "${hermes_dashboard_program}" dashboard \ + --host "${hermes_dashboard_host}" \ + --port "${hermes_dashboard_port}" \ + --no-open \ + --skip-build +} + +hermes_dashboard_stop() +{ + local _sup="" + [ -f "${supervisor_pidfile}" ] && _sup=$(cat "${supervisor_pidfile}" 2>/dev/null) + if [ -n "${_sup}" ] && kill -0 "${_sup}" 2>/dev/null; then + echo "Stopping ${name} (daemon(8) supervisor pid ${_sup})." + kill -TERM "${_sup}" 2>/dev/null + local _n=0 + while kill -0 "${_sup}" 2>/dev/null && [ ${_n} -lt 30 ]; do + sleep 1 + _n=$((_n + 1)) + done + if kill -0 "${_sup}" 2>/dev/null; then + echo "Supervisor did not exit in time; sending SIGKILL." + kill -KILL "${_sup}" 2>/dev/null + fi + else + echo "${name} is not running." + fi + local _ch="" + [ -f "${pidfile}" ] && _ch=$(cat "${pidfile}" 2>/dev/null) + if [ -n "${_ch}" ] && kill -0 "${_ch}" 2>/dev/null; then + kill -TERM "${_ch}" 2>/dev/null + fi + rm -f "${supervisor_pidfile}" "${pidfile}" +} + +health_cmd="hermes_dashboard_health" +status_cmd="hermes_dashboard_status" +hermes_dashboard_status() +{ + hermes_dashboard_health +} + +hermes_dashboard_health() +{ + if [ -f "${pidfile}" ]; then + local _pid + _pid=$(cat "${pidfile}" 2>/dev/null) + if [ -n "${_pid}" ] && kill -0 "${_pid}" 2>/dev/null; then + echo "hermes-dashboard is healthy (pid ${_pid} alive)" + return 0 + fi + fi + echo "hermes-dashboard not running" + return 1 +} + +run_rc_command "$1"