- Setup wizard with auto-detection of OpenClaw paths and Claude CLI - Token sync watcher (inotifywait) for real-time credential updates - Auto-refresh trigger timer that runs Claude CLI every 30 min - Supports Claude CLI in Docker container or on host - Temporary ANTHROPIC_BASE_URL override for container environments - Anthropic model configuration for OpenClaw - Auth profile management (fixes key vs access field) - Systemd services and timers for both sync and trigger - Comprehensive documentation and troubleshooting guides - Re-authentication notification system Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
173 lines
5.1 KiB
Bash
Executable File
173 lines
5.1 KiB
Bash
Executable File
#!/bin/bash
|
|
# verify.sh — Post-install health check for OAuth token sync
|
|
# Run anytime to check if everything is working correctly
|
|
|
|
set -uo pipefail
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m'
|
|
|
|
pass() { echo -e " ${GREEN}[PASS]${NC} $*"; }
|
|
fail() { echo -e " ${RED}[FAIL]${NC} $*"; }
|
|
warn() { echo -e " ${YELLOW}[WARN]${NC} $*"; }
|
|
|
|
ERRORS=0
|
|
|
|
echo ""
|
|
echo "=========================================="
|
|
echo " OAuth Token Sync — Health Check"
|
|
echo "=========================================="
|
|
echo ""
|
|
|
|
# --- 1. Systemd service ---
|
|
echo "1. Systemd service status"
|
|
if systemctl is-active --quiet sync-oauth-token.service 2>/dev/null; then
|
|
pass "sync-oauth-token.service is active"
|
|
else
|
|
fail "sync-oauth-token.service is not running"
|
|
echo " Fix: systemctl start sync-oauth-token.service"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
|
|
if systemctl is-enabled --quiet sync-oauth-token.service 2>/dev/null; then
|
|
pass "Service is enabled (starts on boot)"
|
|
else
|
|
warn "Service is not enabled for boot"
|
|
echo " Fix: systemctl enable sync-oauth-token.service"
|
|
fi
|
|
echo ""
|
|
|
|
# --- 2. inotifywait process ---
|
|
echo "2. File watcher process"
|
|
if pgrep -f inotifywait > /dev/null 2>&1; then
|
|
WATCH_PATH=$(pgrep -af inotifywait | grep -oP '/[^ ]+' | tail -1)
|
|
pass "inotifywait is running (watching: $WATCH_PATH)"
|
|
else
|
|
fail "inotifywait is not running"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
echo ""
|
|
|
|
# --- 3. Source credentials file ---
|
|
echo "3. Claude CLI credentials file"
|
|
# Try to find the watched file from the service
|
|
SYNC_SCRIPT=$(which sync-oauth-token.sh 2>/dev/null || echo "/usr/local/bin/sync-oauth-token.sh")
|
|
if [ -f "$SYNC_SCRIPT" ]; then
|
|
SOURCE_FILE=$(grep 'CLAUDE_CREDS_FILE=' "$SYNC_SCRIPT" | head -1 | cut -d'"' -f2)
|
|
fi
|
|
SOURCE_FILE="${SOURCE_FILE:-/root/.openclaw/workspaces/workspace-claude-proxy/config/.claude/.credentials.json}"
|
|
|
|
if [ -f "$SOURCE_FILE" ]; then
|
|
pass "File exists: $SOURCE_FILE"
|
|
EXPIRES=$(python3 -c "
|
|
import json, time
|
|
with open('$SOURCE_FILE') as f:
|
|
d = json.load(f)
|
|
exp = d['claudeAiOauth']['expiresAt'] / 1000
|
|
remaining = (exp - time.time()) / 3600
|
|
status = 'VALID' if remaining > 0 else 'EXPIRED'
|
|
print(f'{remaining:.1f}h remaining ({status})')
|
|
" 2>/dev/null || echo "parse error")
|
|
if echo "$EXPIRES" | grep -q "VALID"; then
|
|
pass "Token: $EXPIRES"
|
|
else
|
|
fail "Token: $EXPIRES"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
else
|
|
fail "File not found: $SOURCE_FILE"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
echo ""
|
|
|
|
# --- 4. OpenClaw oauth.json ---
|
|
echo "4. OpenClaw oauth.json"
|
|
for path in /root/.openclaw/credentials/oauth.json /home/*/.openclaw/credentials/oauth.json; do
|
|
if [ -f "$path" ]; then
|
|
OAUTH_FILE="$path"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -n "${OAUTH_FILE:-}" ] && [ -f "$OAUTH_FILE" ]; then
|
|
HAS_ACCESS=$(python3 -c "
|
|
import json
|
|
with open('$OAUTH_FILE') as f:
|
|
d = json.load(f)
|
|
a = d.get('anthropic', {})
|
|
print('yes' if a.get('access') else 'no')
|
|
" 2>/dev/null || echo "no")
|
|
if [ "$HAS_ACCESS" = "yes" ]; then
|
|
pass "oauth.json exists with anthropic.access field: $OAUTH_FILE"
|
|
else
|
|
fail "oauth.json exists but missing anthropic.access field"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
else
|
|
fail "oauth.json not found"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
echo ""
|
|
|
|
# --- 5. .env file ---
|
|
echo "5. Environment file (.env)"
|
|
for path in /root/openclaw/.env; do
|
|
if [ -f "$path" ]; then
|
|
ENV_FILE="$path"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -n "${ENV_FILE:-}" ] && [ -f "$ENV_FILE" ]; then
|
|
if grep -q 'ANTHROPIC_OAUTH_TOKEN=' "$ENV_FILE"; then
|
|
TOKEN_PREFIX=$(grep 'ANTHROPIC_OAUTH_TOKEN=' "$ENV_FILE" | head -1 | cut -d'"' -f2 | cut -c1-20)
|
|
pass ".env has ANTHROPIC_OAUTH_TOKEN: ${TOKEN_PREFIX}..."
|
|
else
|
|
fail ".env missing ANTHROPIC_OAUTH_TOKEN"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
else
|
|
fail ".env file not found"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
echo ""
|
|
|
|
# --- 6. Gateway container ---
|
|
echo "6. Gateway container"
|
|
GATEWAY=$(docker ps --filter name=openclaw --format '{{.Names}}' 2>/dev/null | grep gateway | head -1)
|
|
if [ -n "$GATEWAY" ]; then
|
|
UPTIME=$(docker ps --filter "name=$GATEWAY" --format '{{.Status}}' 2>/dev/null)
|
|
pass "Gateway running: $GATEWAY ($UPTIME)"
|
|
|
|
# Check container env var matches .env
|
|
CONTAINER_TOKEN=$(docker exec "$GATEWAY" printenv ANTHROPIC_OAUTH_TOKEN 2>/dev/null | cut -c1-20)
|
|
if [ -n "$CONTAINER_TOKEN" ]; then
|
|
pass "Container has ANTHROPIC_OAUTH_TOKEN: ${CONTAINER_TOKEN}..."
|
|
else
|
|
warn "Container missing ANTHROPIC_OAUTH_TOKEN env var"
|
|
fi
|
|
else
|
|
fail "No OpenClaw gateway container found"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
echo ""
|
|
|
|
# --- Summary ---
|
|
echo "=========================================="
|
|
if [ "$ERRORS" -eq 0 ]; then
|
|
echo -e " ${GREEN}All checks passed${NC}"
|
|
else
|
|
echo -e " ${RED}$ERRORS check(s) failed${NC}"
|
|
fi
|
|
echo "=========================================="
|
|
echo ""
|
|
echo "Useful commands:"
|
|
echo " journalctl -u sync-oauth-token.service -f # Watch sync logs"
|
|
echo " systemctl restart sync-oauth-token.service # Force re-sync"
|
|
echo " ./scripts/verify.sh # Run this check again"
|
|
echo ""
|
|
|
|
exit $ERRORS
|