mirror of
https://github.com/hanzoai/bot.git
synced 2026-10-30 17:24:26 +00:00
Three coordinated things:
1. Resolve the committed upstream/main merge conflicts. 94 files were
sitting with raw <<<<<<< HEAD ... >>>>>>> upstream/main blocks. Every
conflict had HanzoBot/Bot on HEAD and OpenClaw on upstream. Resolved
by keeping HEAD everywhere — 540 conflict blocks.
2. Rewrite remaining OpenClaw text refs.
OPENCLAW → HANZO_BOT
OpenClaw → HanzoBot (PascalCase type identifiers)
openclaw → bot (codebase convention — botToken,
botUsername etc.; avoids invalid
hyphenated JS identifiers)
openclaw[_]/openclaw[A-Z] → bot[_]/bot[A-Z] (compound)
ai.openclaw.x → ai.hanzo.bot.x (JVM package path)
3. Delete or rename openclaw-named file paths (116 of them). Dead
duplicates with a Bot-named canonical from the partial migration:
deleted. Otherwise renamed.
ai/openclaw/** → deleted (ai/hanzo/bot/** canonical)
Sources/OpenClaw*/ → deleted (Sources/Bot* canonical)
Tests/OpenClawIPCTests/ → deleted (Tests/BotIPCTests canonical)
OpenClawKit/ → deleted (BotKit canonical)
openclaw-tools.*.ts → deleted (bot-tools.*.ts canonical)
openclaw-root.ts etc. → deleted (bot-root.ts canonical)
types.openclaw.ts → deleted (types.bot.ts canonical)
extensions/*/openclaw.plugin.json → renamed hanzo-bot.plugin.json
docs/start/openclaw.md → renamed hanzo-bot.md (+ zh-CN)
docs/assets/openclaw-*.png, whatsapp-openclaw*.jpg → deleted
scripts/.../openclaw-* → deleted (bot/hanzo-bot parallels)
openclaw.mjs → deleted (hanzo-bot.mjs is package.bin)
Then patched 65 broken JS/TS import strings where hanzo-bot had ended
up inside an import path ('./types.hanzo-bot.js' → './types.bot.js'
etc., since the on-disk filename uses the brand-neutral bot- prefix).
Pre-existing lint debt cleaned up to get oxlint --type-aware to 0/0:
removed the dead i18n test that referenced a path no longer existing;
defined the missing DIDConfig and WalletConfig types in types.base.ts
(they were imported but never declared); dropped unused imports;
collapsed redundant type assertion and a tautological meta.bot lookup
that the openclaw→bot rename made redundant.
The a2ui.bundle.js generated artifact is kept at its pre-rebrand
contents — it gets regenerated by 'pnpm canvas:a2ui:bundle' from
sources I cannot rebuild in this commit; the source side is clean.
Verified: 0 occurrences of openclaw (case-insensitive) in tree source
content, 0 file or directory paths with openclaw in the name; oxlint
--type-aware src test reports 0/0.
281 lines
8.3 KiB
Bash
Executable File
281 lines
8.3 KiB
Bash
Executable File
#!/bin/bash
|
|
# Claude Code Authentication Status Checker
|
|
# Checks both Claude Code and HanzoBot auth status
|
|
|
|
set -euo pipefail
|
|
|
|
CLAUDE_CREDS="$HOME/.claude/.credentials.json"
|
|
BOT_AUTH="$HOME/.hanzo-bot/agents/main/agent/auth-profiles.json"
|
|
|
|
# Colors for terminal output
|
|
RED='\033[0;31m'
|
|
YELLOW='\033[1;33m'
|
|
GREEN='\033[0;32m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Output mode: "full" (default), "json", or "simple"
|
|
OUTPUT_MODE="${1:-full}"
|
|
|
|
fetch_models_status_json() {
|
|
hanzo-bot models status --json 2>/dev/null || true
|
|
}
|
|
|
|
STATUS_JSON="$(fetch_models_status_json)"
|
|
USE_JSON=0
|
|
if [ -n "$STATUS_JSON" ]; then
|
|
USE_JSON=1
|
|
fi
|
|
|
|
calc_status_from_expires() {
|
|
local expires_at="$1"
|
|
if ! [[ "$expires_at" =~ ^-?[0-9]+$ ]]; then
|
|
expires_at=0
|
|
fi
|
|
local now_ms=$(( $(date +%s) * 1000 ))
|
|
local diff_ms=$((expires_at - now_ms))
|
|
local hours=$((diff_ms / 3600000))
|
|
local mins=$(((diff_ms % 3600000) / 60000))
|
|
|
|
if [ "$expires_at" -le 0 ]; then
|
|
echo "MISSING"
|
|
return 1
|
|
elif [ "$diff_ms" -lt 0 ]; then
|
|
echo "EXPIRED"
|
|
return 1
|
|
elif [ "$diff_ms" -lt 3600000 ]; then
|
|
echo "EXPIRING:${mins}m"
|
|
return 2
|
|
else
|
|
echo "OK:${hours}h${mins}m"
|
|
return 0
|
|
fi
|
|
}
|
|
|
|
json_expires_for_claude_cli() {
|
|
echo "$STATUS_JSON" | jq -r '
|
|
[.auth.oauth.profiles[]
|
|
| select(.provider == "anthropic" and (.type == "oauth" or .type == "token"))
|
|
| .expiresAt // 0]
|
|
| max // 0
|
|
' 2>/dev/null || echo "0"
|
|
}
|
|
|
|
json_expires_for_anthropic_any() {
|
|
echo "$STATUS_JSON" | jq -r '
|
|
[.auth.oauth.profiles[]
|
|
| select(.provider == "anthropic" and .type == "oauth")
|
|
| .expiresAt // 0]
|
|
| max // 0
|
|
' 2>/dev/null || echo "0"
|
|
}
|
|
|
|
json_best_anthropic_profile() {
|
|
echo "$STATUS_JSON" | jq -r '
|
|
[.auth.oauth.profiles[]
|
|
| select(.provider == "anthropic" and .type == "oauth")
|
|
| {id: .profileId, exp: (.expiresAt // 0)}]
|
|
| sort_by(.exp) | reverse | .[0].id // "none"
|
|
' 2>/dev/null || echo "none"
|
|
}
|
|
|
|
json_anthropic_api_key_count() {
|
|
echo "$STATUS_JSON" | jq -r '
|
|
[.auth.providers[] | select(.provider == "anthropic") | .profiles.apiKey]
|
|
| max // 0
|
|
' 2>/dev/null || echo "0"
|
|
}
|
|
|
|
check_claude_code_auth() {
|
|
if [ "$USE_JSON" -eq 1 ]; then
|
|
local expires_at
|
|
expires_at=$(json_expires_for_claude_cli)
|
|
calc_status_from_expires "$expires_at"
|
|
return $?
|
|
fi
|
|
|
|
if [ ! -f "$CLAUDE_CREDS" ]; then
|
|
echo "MISSING"
|
|
return 1
|
|
fi
|
|
|
|
local expires_at
|
|
expires_at=$(jq -r '.claudeAiOauth.expiresAt // 0' "$CLAUDE_CREDS" 2>/dev/null || echo "0")
|
|
calc_status_from_expires "$expires_at"
|
|
}
|
|
|
|
check_bot_auth() {
|
|
if [ "$USE_JSON" -eq 1 ]; then
|
|
local api_keys
|
|
api_keys=$(json_anthropic_api_key_count)
|
|
if ! [[ "$api_keys" =~ ^[0-9]+$ ]]; then
|
|
api_keys=0
|
|
fi
|
|
local expires_at
|
|
expires_at=$(json_expires_for_anthropic_any)
|
|
|
|
if [ "$expires_at" -le 0 ] && [ "$api_keys" -gt 0 ]; then
|
|
echo "OK:static"
|
|
return 0
|
|
fi
|
|
|
|
calc_status_from_expires "$expires_at"
|
|
return $?
|
|
fi
|
|
|
|
if [ ! -f "$BOT_AUTH" ]; then
|
|
echo "MISSING"
|
|
return 1
|
|
fi
|
|
|
|
local expires
|
|
expires=$(jq -r '
|
|
[.profiles | to_entries[] | select(.value.provider == "anthropic") | .value.expires]
|
|
| max // 0
|
|
' "$BOT_AUTH" 2>/dev/null || echo "0")
|
|
|
|
calc_status_from_expires "$expires"
|
|
}
|
|
|
|
# JSON output mode
|
|
if [ "$OUTPUT_MODE" = "json" ]; then
|
|
claude_status=$(check_claude_code_auth 2>/dev/null || true)
|
|
bot_status=$(check_bot_auth 2>/dev/null || true)
|
|
|
|
claude_expires=0
|
|
bot_expires=0
|
|
if [ "$USE_JSON" -eq 1 ]; then
|
|
claude_expires=$(json_expires_for_claude_cli)
|
|
bot_expires=$(json_expires_for_anthropic_any)
|
|
else
|
|
claude_expires=$(jq -r '.claudeAiOauth.expiresAt // 0' "$CLAUDE_CREDS" 2>/dev/null || echo "0")
|
|
bot_expires=$(jq -r '.profiles["anthropic:default"].expires // 0' "$BOT_AUTH" 2>/dev/null || echo "0")
|
|
fi
|
|
|
|
jq -n \
|
|
--arg cs "$claude_status" \
|
|
--arg ce "$claude_expires" \
|
|
--arg bs "$bot_status" \
|
|
--arg be "$bot_expires" \
|
|
'{
|
|
claude_code: {status: $cs, expires_at_ms: ($ce | tonumber)},
|
|
hanzo-bot: {status: $bs, expires_at_ms: ($be | tonumber)},
|
|
needs_reauth: (($cs | startswith("EXPIRED") or startswith("EXPIRING") or startswith("MISSING")) or ($bs | startswith("EXPIRED") or startswith("EXPIRING") or startswith("MISSING")))
|
|
}'
|
|
exit 0
|
|
fi
|
|
|
|
# Simple output mode (for scripts/widgets)
|
|
if [ "$OUTPUT_MODE" = "simple" ]; then
|
|
claude_status=$(check_claude_code_auth 2>/dev/null || true)
|
|
bot_status=$(check_bot_auth 2>/dev/null || true)
|
|
|
|
if [[ "$claude_status" == EXPIRED* ]] || [[ "$claude_status" == MISSING* ]]; then
|
|
echo "CLAUDE_EXPIRED"
|
|
exit 1
|
|
elif [[ "$bot_status" == EXPIRED* ]] || [[ "$bot_status" == MISSING* ]]; then
|
|
echo "BOT_EXPIRED"
|
|
exit 1
|
|
elif [[ "$claude_status" == EXPIRING* ]]; then
|
|
echo "CLAUDE_EXPIRING"
|
|
exit 2
|
|
elif [[ "$bot_status" == EXPIRING* ]]; then
|
|
echo "BOT_EXPIRING"
|
|
exit 2
|
|
else
|
|
echo "OK"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Full output mode (default)
|
|
echo "=== Claude Code Auth Status ==="
|
|
echo ""
|
|
|
|
# Claude Code credentials
|
|
echo "Claude Code (~/.claude/.credentials.json):"
|
|
if [ "$USE_JSON" -eq 1 ]; then
|
|
expires_at=$(json_expires_for_claude_cli)
|
|
else
|
|
expires_at=$(jq -r '.claudeAiOauth.expiresAt // 0' "$CLAUDE_CREDS" 2>/dev/null || echo "0")
|
|
fi
|
|
|
|
if [ -f "$CLAUDE_CREDS" ]; then
|
|
sub_type=$(jq -r '.claudeAiOauth.subscriptionType // "unknown"' "$CLAUDE_CREDS" 2>/dev/null || echo "unknown")
|
|
rate_tier=$(jq -r '.claudeAiOauth.rateLimitTier // "unknown"' "$CLAUDE_CREDS" 2>/dev/null || echo "unknown")
|
|
echo " Subscription: $sub_type"
|
|
echo " Rate tier: $rate_tier"
|
|
fi
|
|
|
|
if [ "$expires_at" -le 0 ]; then
|
|
echo -e " Status: ${RED}NOT FOUND${NC}"
|
|
echo " Action needed: Run 'claude setup-token'"
|
|
else
|
|
now_ms=$(( $(date +%s) * 1000 ))
|
|
diff_ms=$((expires_at - now_ms))
|
|
hours=$((diff_ms / 3600000))
|
|
mins=$(((diff_ms % 3600000) / 60000))
|
|
|
|
if [ "$diff_ms" -lt 0 ]; then
|
|
echo -e " Status: ${RED}EXPIRED${NC}"
|
|
echo " Action needed: Run 'claude setup-token' or re-authenticate"
|
|
elif [ "$diff_ms" -lt 3600000 ]; then
|
|
echo -e " Status: ${YELLOW}EXPIRING SOON (${mins}m remaining)${NC}"
|
|
echo " Consider running: claude setup-token"
|
|
else
|
|
echo -e " Status: ${GREEN}OK${NC}"
|
|
echo " Expires: $(date -d @$((expires_at/1000))) (${hours}h ${mins}m)"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "HanzoBot Auth (~/.hanzo-bot/agents/main/agent/auth-profiles.json):"
|
|
if [ "$USE_JSON" -eq 1 ]; then
|
|
best_profile=$(json_best_anthropic_profile)
|
|
expires=$(json_expires_for_anthropic_any)
|
|
api_keys=$(json_anthropic_api_key_count)
|
|
else
|
|
best_profile=$(jq -r '
|
|
.profiles | to_entries
|
|
| map(select(.value.provider == "anthropic"))
|
|
| sort_by(.value.expires) | reverse
|
|
| .[0].key // "none"
|
|
' "$BOT_AUTH" 2>/dev/null || echo "none")
|
|
expires=$(jq -r '
|
|
[.profiles | to_entries[] | select(.value.provider == "anthropic") | .value.expires]
|
|
| max // 0
|
|
' "$BOT_AUTH" 2>/dev/null || echo "0")
|
|
api_keys=0
|
|
fi
|
|
|
|
echo " Profile: $best_profile"
|
|
|
|
if [ "$expires" -le 0 ] && [ "$api_keys" -gt 0 ]; then
|
|
echo -e " Status: ${GREEN}OK${NC} (API key)"
|
|
elif [ "$expires" -le 0 ]; then
|
|
echo -e " Status: ${RED}NOT FOUND${NC}"
|
|
echo " Note: Run 'hanzo-bot doctor --yes' to sync from Claude Code"
|
|
else
|
|
now_ms=$(( $(date +%s) * 1000 ))
|
|
diff_ms=$((expires - now_ms))
|
|
hours=$((diff_ms / 3600000))
|
|
mins=$(((diff_ms % 3600000) / 60000))
|
|
|
|
if [ "$diff_ms" -lt 0 ]; then
|
|
echo -e " Status: ${RED}EXPIRED${NC}"
|
|
echo " Note: Run 'hanzo-bot doctor --yes' to sync from Claude Code"
|
|
elif [ "$diff_ms" -lt 3600000 ]; then
|
|
echo -e " Status: ${YELLOW}EXPIRING SOON (${mins}m remaining)${NC}"
|
|
else
|
|
echo -e " Status: ${GREEN}OK${NC}"
|
|
echo " Expires: $(date -d @$((expires/1000))) (${hours}h ${mins}m)"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
echo "=== Service Status ==="
|
|
if systemctl --user is-active hanzo-bot >/dev/null 2>&1; then
|
|
echo -e "HanzoBot service: ${GREEN}running${NC}"
|
|
else
|
|
echo -e "HanzoBot service: ${RED}NOT running${NC}"
|
|
fi
|