fix: persistent daemon startup, plugin integration, mobile fallback

- Hook handler now loads .env.daemon for proper config (plugin URL/secret, bot user ID)
- Hook logs to /tmp/status-watcher.log instead of /dev/null
- Added .env.daemon config file (.gitignored - contains tokens)
- Added start-daemon.sh convenience script
- Plugin mode: mobile fallback updates post message field with formatted markdown
- Fixed unbounded lines array in status-watcher (capped at 50)
- Added session marker to formatter output for restart recovery
- Go plugin: added updatePostMessageForMobile() for dual-render strategy
  (webapp gets custom React component, mobile gets markdown in message field)

Fixes: daemon silently dying, no plugin connection, mobile showing blank posts
This commit is contained in:
sol
2026-03-08 07:42:18 +00:00
parent 0d0e6e9d90
commit 09441b34c1
7 changed files with 268 additions and 12 deletions

78
start-daemon.sh Executable file
View File

@@ -0,0 +1,78 @@
#!/bin/bash
# start-daemon.sh — Start the live-status watcher daemon with proper config.
# This script is the canonical way to start the daemon. It loads env vars,
# ensures only one instance runs, and redirects logs properly.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_FILE="${LIVESTATUS_LOG_FILE:-/tmp/status-watcher.log}"
PID_FILE="${PID_FILE:-/tmp/status-watcher.pid}"
ENV_FILE="${SCRIPT_DIR}/.env.daemon"
# Load .env.daemon if it exists
if [ -f "$ENV_FILE" ]; then
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
fi
# Required env vars with defaults
export MM_BOT_TOKEN="${MM_BOT_TOKEN:?MM_BOT_TOKEN is required}"
export MM_BASE_URL="${MM_BASE_URL:-https://slack.solio.tech}"
export MM_BOT_USER_ID="${MM_BOT_USER_ID:-eqtkymoej7rw7dp8xbh7hywzrr}"
export TRANSCRIPT_DIR="${TRANSCRIPT_DIR:-/home/node/.openclaw/agents}"
export LOG_LEVEL="${LOG_LEVEL:-info}"
export IDLE_TIMEOUT_S="${IDLE_TIMEOUT_S:-60}"
export SESSION_POLL_MS="${SESSION_POLL_MS:-2000}"
export MAX_ACTIVE_SESSIONS="${MAX_ACTIVE_SESSIONS:-20}"
export MAX_STATUS_LINES="${MAX_STATUS_LINES:-20}"
export HEALTH_PORT="${HEALTH_PORT:-9090}"
export PID_FILE
export OFFSET_FILE="${OFFSET_FILE:-/tmp/status-watcher-offsets.json}"
# Plugin config (optional but recommended)
export PLUGIN_ENABLED="${PLUGIN_ENABLED:-true}"
export PLUGIN_URL="${PLUGIN_URL:-https://slack.solio.tech/plugins/com.openclaw.livestatus}"
export PLUGIN_SECRET="${PLUGIN_SECRET:-}"
# Kill existing daemon if running
if [ -f "$PID_FILE" ]; then
OLD_PID=$(cat "$PID_FILE" 2>/dev/null || true)
if [ -n "$OLD_PID" ] && kill -0 "$OLD_PID" 2>/dev/null; then
echo "Stopping existing daemon (PID $OLD_PID)..."
kill "$OLD_PID" 2>/dev/null || true
sleep 1
fi
rm -f "$PID_FILE"
fi
# Start daemon with proper logging
echo "Starting status watcher daemon..."
echo " Log file: $LOG_FILE"
echo " PID file: $PID_FILE"
echo " Plugin: ${PLUGIN_ENABLED} (${PLUGIN_URL:-not configured})"
cd "$SCRIPT_DIR"
node src/watcher-manager.js start >> "$LOG_FILE" 2>&1 &
DAEMON_PID=$!
# Wait for PID file
for i in $(seq 1 10); do
if [ -f "$PID_FILE" ]; then
echo "Daemon started (PID $(cat "$PID_FILE"))"
exit 0
fi
sleep 0.5
done
# Check if process is still running
if kill -0 "$DAEMON_PID" 2>/dev/null; then
echo "Daemon started (PID $DAEMON_PID) but PID file not created yet"
exit 0
else
echo "ERROR: Daemon failed to start. Check $LOG_FILE"
tail -20 "$LOG_FILE" 2>/dev/null
exit 1
fi