sync(visuals): hardened panel indicator + wallpaper on join from layered-soul #74
2 changed files with 123 additions and 42 deletions
|
|
@ -2,11 +2,33 @@
|
|||
# One-click "Join Hive" — registers this machine as a Colibri agent.
|
||||
# Runs in a visible terminal so the operator sees the result.
|
||||
# Idempotent: safe to re-run on an already-registered agent.
|
||||
set -e
|
||||
|
||||
SOCKET="${COLIBRI_SOCKET:-/var/run/colibri/colibri.sock}"
|
||||
PROVIDER_ENV="/usr/local/etc/colibri/provider.env"
|
||||
|
||||
finish() {
|
||||
_code="${1:-0}"
|
||||
echo ""
|
||||
echo "Press Enter to close."
|
||||
read -r _
|
||||
exit "${_code}"
|
||||
}
|
||||
|
||||
have() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
provider_env_has_bw_creds() {
|
||||
_check='test -f "$1" && grep -Eq "^BW_CLIENTID=.+" "$1" && grep -Eq "^BW_CLIENTSECRET=.+" "$1" && grep -Eq "^BW_PASSWORD=.+" "$1"'
|
||||
|
||||
if have mdo; then
|
||||
mdo -u root sh -c "${_check}" sh "${PROVIDER_ENV}" >/dev/null 2>&1
|
||||
return $?
|
||||
fi
|
||||
|
||||
sh -c "${_check}" sh "${PROVIDER_ENV}" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
echo "========================================"
|
||||
echo " Clawdie — Join Hive"
|
||||
echo "========================================"
|
||||
|
|
@ -15,56 +37,108 @@ echo ""
|
|||
# 1. Check daemon
|
||||
if [ ! -S "$SOCKET" ]; then
|
||||
echo "[1/4] Starting colibri daemon..."
|
||||
mdo -u root service colibri_daemon start
|
||||
sleep 2
|
||||
if have mdo; then
|
||||
if ! mdo -u root service colibri_daemon start; then
|
||||
echo " WARNING: could not start colibri_daemon via mdo."
|
||||
fi
|
||||
elif [ "$(id -u)" -eq 0 ]; then
|
||||
if ! service colibri_daemon start; then
|
||||
echo " WARNING: could not start colibri_daemon."
|
||||
fi
|
||||
else
|
||||
echo " WARNING: mdo is unavailable and this user is not root."
|
||||
fi
|
||||
|
||||
_tries=0
|
||||
while [ "$_tries" -lt 5 ] && [ ! -S "$SOCKET" ]; do
|
||||
sleep 1
|
||||
_tries=$(( _tries + 1 ))
|
||||
done
|
||||
else
|
||||
echo "[1/4] Daemon already running."
|
||||
fi
|
||||
|
||||
# 2. Vault creds
|
||||
if [ ! -S "$SOCKET" ]; then
|
||||
echo " ERROR: Colibri socket is still missing: ${SOCKET}"
|
||||
echo " Check: mdo -u root service colibri_daemon status"
|
||||
finish 1
|
||||
fi
|
||||
|
||||
# 2. Vault creds. provider.env is intentionally 0600, so check via mdo when possible.
|
||||
echo "[2/4] Checking vault credentials..."
|
||||
if [ -f "$PROVIDER_ENV" ] && grep -q 'BW_CLIENTID=.' "$PROVIDER_ENV" 2>/dev/null; then
|
||||
echo " provider.env present with credentials."
|
||||
if provider_env_has_bw_creds; then
|
||||
echo " provider.env contains Vaultwarden bootstrap credential fields."
|
||||
else
|
||||
echo " WARNING: provider.env missing or empty."
|
||||
echo " Vault provisioning will be skipped."
|
||||
echo " Edit ${PROVIDER_ENV} and re-run."
|
||||
echo " WARNING: provider.env is missing, unreadable, or lacks BW_CLIENTID/BW_CLIENTSECRET/BW_PASSWORD."
|
||||
echo " Vault provisioning will be skipped until the operator adds them."
|
||||
echo " Edit ${PROVIDER_ENV} and keep it mode 0600, then re-run."
|
||||
fi
|
||||
|
||||
# 3. Detect capabilities
|
||||
HOST=$(hostname)
|
||||
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
|
||||
HOST=$(hostname 2>/dev/null || echo "clawdie-live")
|
||||
OS=$(uname -s 2>/dev/null | tr '[:upper:]' '[:lower:]')
|
||||
[ -n "$OS" ] || OS="unknown"
|
||||
CAPS="$OS,shell"
|
||||
|
||||
# Add optional capabilities
|
||||
which colibri >/dev/null 2>&1 && CAPS="$CAPS,colibri"
|
||||
which hermes >/dev/null 2>&1 && CAPS="$CAPS,hermes"
|
||||
which pi >/dev/null 2>&1 && CAPS="$CAPS,pi"
|
||||
tailscale status >/dev/null 2>&1 && CAPS="$CAPS,tailscale"
|
||||
have colibri && CAPS="$CAPS,colibri"
|
||||
have hermes && CAPS="$CAPS,hermes"
|
||||
have pi && CAPS="$CAPS,pi"
|
||||
if have tailscale && tailscale status >/dev/null 2>&1; then
|
||||
CAPS="$CAPS,tailscale"
|
||||
fi
|
||||
[ "$OS" = "freebsd" ] && CAPS="$CAPS,rc.d,jail,zfs"
|
||||
|
||||
if have python3; then
|
||||
CAPS_JSON=$(printf '%s' "$CAPS" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read().strip().split(",")))' 2>/dev/null)
|
||||
else
|
||||
CAPS_JSON='["shell"]'
|
||||
fi
|
||||
[ -n "$CAPS_JSON" ] || CAPS_JSON='["shell"]'
|
||||
|
||||
AGENT_NAME="${HOST}"
|
||||
echo "[3/4] Registering agent: ${AGENT_NAME}"
|
||||
echo " capabilities: ${CAPS}"
|
||||
|
||||
if ! have nc; then
|
||||
echo " ERROR: nc is not installed; cannot talk to ${SOCKET}."
|
||||
finish 1
|
||||
fi
|
||||
|
||||
RESP=$(printf '{"cmd":"register-agent","name":"%s","capabilities":%s}\n' \
|
||||
"$AGENT_NAME" "$(echo "$CAPS" | python3 -c "import sys; print(__import__('json').dumps(sys.stdin.read().strip().split(',')))")" \
|
||||
"$AGENT_NAME" "$CAPS_JSON" \
|
||||
| nc -U "$SOCKET" -w 3 2>/dev/null)
|
||||
|
||||
if echo "$RESP" | grep -q '"ok":true'; then
|
||||
echo " registered."
|
||||
elif echo "$RESP" | grep -q 'already exists'; then
|
||||
elif echo "$RESP" | grep -Eiq 'already exists|unique constraint|constraint failed|agents\.name'; then
|
||||
echo " already registered (idempotent)."
|
||||
else
|
||||
echo " registration note: ${RESP}"
|
||||
echo " registration did not complete cleanly."
|
||||
if [ -n "$RESP" ]; then
|
||||
echo " response: ${RESP}"
|
||||
else
|
||||
echo " no response from ${SOCKET}"
|
||||
fi
|
||||
finish 1
|
||||
fi
|
||||
|
||||
# 4. Start poll loop
|
||||
# 4. Apply identity wallpaper as visual confirmation
|
||||
echo "[4/4] Agent ${AGENT_NAME} is live on the Colibri board."
|
||||
echo ""
|
||||
|
||||
if have clawdie-wallpaper-gen; then
|
||||
echo " Setting identity wallpaper..."
|
||||
if have xfconf-query; then
|
||||
WP="/tmp/clawdie-wallpaper.png"
|
||||
clawdie-wallpaper-gen "$WP" 2>/dev/null && \
|
||||
xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/workspace0/last-image -s "$WP" 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " Check: colibri status"
|
||||
echo " Tasks: colibri list-tasks --status started"
|
||||
echo " Board: colibri list-agents"
|
||||
echo ""
|
||||
echo "Hive joined. Press Enter to close."
|
||||
read -r _
|
||||
echo "Hive joined."
|
||||
finish 0
|
||||
|
|
|
|||
|
|
@ -1,32 +1,39 @@
|
|||
#!/bin/sh
|
||||
# xfce4-genmon panel indicator — polls colibri daemon health.
|
||||
# Install: add a Generic Monitor panel item pointing to this script.
|
||||
# Refresh interval: 30s.
|
||||
#
|
||||
# Output: green/red dot + agent count + task count.
|
||||
# Wired into a Generic Monitor panel item with 30s refresh.
|
||||
# Output: genmon XML with green/red dot + agent count + task count.
|
||||
# 🟢 2 agents · 3 tasks
|
||||
# 🔴 daemon down
|
||||
|
||||
SOCKET="${COLIBRI_SOCKET:-/var/run/colibri/colibri.sock}"
|
||||
TOOLTIP=""
|
||||
|
||||
if [ -S "$SOCKET" ]; then
|
||||
STATUS=$(printf '{"cmd":"status"}\n' | nc -U "$SOCKET" -w 2 2>/dev/null)
|
||||
if [ -n "$STATUS" ]; then
|
||||
AGENTS=$(echo "$STATUS" | python3 -c "import sys,json; d=json.load(sys.stdin)['data']; print(d['agents'])" 2>/dev/null)
|
||||
TASKS=$(echo "$STATUS" | python3 -c "import sys,json; d=json.load(sys.stdin)['data']; t=d['tasks']; print(t['started'])" 2>/dev/null)
|
||||
HOST=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['host'])" 2>/dev/null)
|
||||
have() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
echo "<txt>🟢 ${AGENTS} agents · ${TASKS} tasks</txt>"
|
||||
TOOLTIP="Colibri: ${HOST} | socket: ${SOCKET} | agents: ${AGENTS} | started tasks: ${TASKS}"
|
||||
else
|
||||
echo "<txt>🔴 no response</txt>"
|
||||
TOOLTIP="Colibri socket exists but not responding"
|
||||
fi
|
||||
else
|
||||
echo "<txt>🔴 down</txt>"
|
||||
TOOLTIP="Colibri daemon not running (no socket at ${SOCKET})"
|
||||
if ! have nc || ! have python3; then
|
||||
echo "<txt>⚠ missing deps</txt>"
|
||||
echo "<tool>nc and python3 required for colibri panel indicator</tool>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "<tool>${TOOLTIP}</tool>"
|
||||
if [ ! -S "$SOCKET" ]; then
|
||||
echo "<txt>🔴 down</txt>"
|
||||
echo "<tool>Colibri daemon not running (no socket at ${SOCKET})</tool>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
STATUS=$(printf '{"cmd":"status"}\n' | nc -U "$SOCKET" -w 2 2>/dev/null)
|
||||
if [ -z "$STATUS" ]; then
|
||||
echo "<txt>🔴 no response</txt>"
|
||||
echo "<tool>Colibri socket exists but not responding</tool>"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
AGENTS=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['agents'])" 2>/dev/null)
|
||||
TASKS=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['tasks']['started'])" 2>/dev/null)
|
||||
HOST=$(echo "$STATUS" | python3 -c "import sys,json; print(json.load(sys.stdin)['data']['host'])" 2>/dev/null)
|
||||
|
||||
echo "<txt>🟢 ${AGENTS:-?} agents · ${TASKS:-?} tasks</txt>"
|
||||
echo "<tool>Colibri: ${HOST:-?} | socket: ${SOCKET} | agents: ${AGENTS:-?} | started tasks: ${TASKS:-?}</tool>"
|
||||
echo "<txtclick>xfce4-terminal --title 'Colibri Status' --command 'colibri status'</txtclick>"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue