135 lines
3.7 KiB
Bash
Executable File
135 lines
3.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
CONFIG_PATH="${AUTH_WATCHDOG_CONFIG:-$ROOT_DIR/config/copilot-auth-watchdog.config.json}"
|
|
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|
echo "[copilot-auth-watchdog] jq is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
expand_tilde() {
|
|
local p="$1"
|
|
if [[ "$p" == "~" ]]; then
|
|
echo "$HOME"
|
|
elif [[ "$p" == "~/"* ]]; then
|
|
echo "$HOME/${p#~/}"
|
|
else
|
|
echo "$p"
|
|
fi
|
|
}
|
|
|
|
now_ms() {
|
|
python3 - <<'PY'
|
|
import time
|
|
print(int(time.time()*1000))
|
|
PY
|
|
}
|
|
|
|
send_notice() {
|
|
local text="$1"
|
|
local last_channel="$2"
|
|
local last_to="$3"
|
|
|
|
if [[ -z "$last_channel" || -z "$last_to" ]]; then
|
|
echo "[copilot-auth-watchdog] notice skipped (missing channel/target): $text" >&2
|
|
return 0
|
|
fi
|
|
|
|
local target="$last_to"
|
|
if [[ "$target" == *:* ]]; then
|
|
target="${target#*:}"
|
|
fi
|
|
|
|
openclaw message send \
|
|
--channel "$last_channel" \
|
|
--target "$target" \
|
|
--message "$text" \
|
|
>/dev/null 2>&1 || true
|
|
}
|
|
|
|
if [[ ! -f "$CONFIG_PATH" ]]; then
|
|
echo "[copilot-auth-watchdog] missing config: $CONFIG_PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
enabled="$(jq -r '.enabled // true' "$CONFIG_PATH")"
|
|
if [[ "$enabled" != "true" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
session_key="$(jq -r '.sessionKey // "agent:main:main"' "$CONFIG_PATH")"
|
|
alert_interval_min="$(jq -r '.minAlertIntervalMinutes // 30' "$CONFIG_PATH")"
|
|
state_file_raw="$(jq -r '.stateFile // "~/.openclaw/copilot-auth-watchdog-state.json"' "$CONFIG_PATH")"
|
|
state_file="$(expand_tilde "$state_file_raw")"
|
|
check_model_status="$(jq -r '.checkOpenClawModelStatus // true' "$CONFIG_PATH")"
|
|
|
|
state_dir="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
|
|
sessions_file="$state_dir/agents/main/sessions/sessions.json"
|
|
last_channel=""
|
|
last_to=""
|
|
if [[ -r "$sessions_file" ]]; then
|
|
session_json="$(jq -c --arg key "$session_key" '.[$key] // {}' "$sessions_file" 2>/dev/null || true)"
|
|
if [[ -n "$session_json" && "$session_json" != "{}" ]]; then
|
|
last_channel="$(jq -r '.lastChannel // empty' <<<"$session_json")"
|
|
last_to="$(jq -r '.lastTo // empty' <<<"$session_json")"
|
|
fi
|
|
fi
|
|
|
|
declare -a issues=()
|
|
|
|
if ! command -v copilot >/dev/null 2>&1; then
|
|
issues+=("copilot CLI not installed; run setup_openclaw_copilot.sh")
|
|
else
|
|
set +e
|
|
copilot_out="$(copilot auth status 2>&1)"
|
|
copilot_rc=$?
|
|
set -e
|
|
|
|
if [[ $copilot_rc -ne 0 ]]; then
|
|
issues+=("copilot auth status failed; run: copilot auth login")
|
|
elif echo "$copilot_out" | grep -Eiq 'not authenticated|not logged|login required|expired|unauthorized|invalid'; then
|
|
issues+=("copilot auth not healthy; run: copilot auth login")
|
|
fi
|
|
fi
|
|
|
|
if [[ "$check_model_status" == "true" ]]; then
|
|
if ! command -v openclaw >/dev/null 2>&1; then
|
|
issues+=("openclaw CLI not installed")
|
|
else
|
|
if ! openclaw models status --check >/dev/null 2>&1; then
|
|
issues+=("openclaw model auth check failed; run: openclaw models status --json and copilot auth login")
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [[ ${#issues[@]} -eq 0 ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
mkdir -p "$(dirname "$state_file")"
|
|
if [[ ! -f "$state_file" ]]; then
|
|
printf '{}\n' > "$state_file"
|
|
fi
|
|
|
|
state_json="$(cat "$state_file")"
|
|
last_alert_at="$(jq -r --arg key "$session_key" '.[$key].lastAlertAt // 0' <<<"$state_json")"
|
|
if [[ ! "$last_alert_at" =~ ^[0-9]+$ ]]; then
|
|
last_alert_at=0
|
|
fi
|
|
|
|
now="$(now_ms)"
|
|
interval_ms=$((alert_interval_min * 60 * 1000))
|
|
if (( now - last_alert_at < interval_ms )); then
|
|
exit 0
|
|
fi
|
|
|
|
summary="Copilot auth watchdog alert: ${issues[*]}"
|
|
echo "[copilot-auth-watchdog] $summary"
|
|
send_notice "$summary" "$last_channel" "$last_to"
|
|
|
|
state_json="$(jq --arg key "$session_key" --argjson now "$now" '.[$key].lastAlertAt=$now' <<<"$state_json")"
|
|
printf '%s\n' "$state_json" > "$state_file"
|