Files
ai-setup/home-configs/claude/hooks/add-account-hook.sh
vitaly 7a5a977aca feat: поддержка API-ключей в add/switch-account, не только Claude.ai
Хуки add-account и switch-account теперь ветвятся по AI_LAUNCHER:
claude - циклический обход сохранённых Claude.ai аккаунтов,
kimi - добавление и переключение API-ключей по кругу.
Skills обновлены под "account or API key".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 05:21:12 +03:00

152 lines
5.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# UserPromptSubmit hook: перехватывает /add-account.
# 1) сохраняет текущий аккаунт по его реальному email (account-email.sh)
# 2) запускает oauth-логин в фоне (открывает браузер)
# 3) после логина фоновый процесс сам определяет email нового аккаунта по токену
# и сохраняет его credentials + делает current
input=$(cat)
prompt=$(echo "$input" | jq -r '.user_prompt // .prompt // empty' 2>/dev/null)
normalized=$(echo "$prompt" | sed 's|^[[:space:]]*/||; s|[[:space:]]*$||')
# Для /add-account ключ передаётся в том же сообщении, поэтому проверяем префикс.
normalized_cmd=$(echo "$normalized" | awk '{print $1}')
[ "$normalized_cmd" != "add-account" ] && exit 0
LAUNCHER="${AI_LAUNCHER:-claude}"
case "$LAUNCHER" in
claude)
CREDS="$HOME/.claude/.credentials.json"
ACCOUNTS_DIR="$HOME/.claude/accounts"
CURRENT_FILE="$ACCOUNTS_DIR/current"
EMAIL_HELPER="$HOME/.claude/hooks/account-email.sh"
mkdir -p "$ACCOUNTS_DIR"
# Сохраняем текущий активный аккаунт под его реальным email (по токену)
if [ -f "$CREDS" ]; then
cur_email=$(bash "$EMAIL_HELPER" "$CREDS" 2>/dev/null)
if [ -n "$cur_email" ]; then
cp "$CREDS" "$ACCOUNTS_DIR/${cur_email}.credentials.json"
chmod 600 "$ACCOUNTS_DIR/${cur_email}.credentials.json"
echo "$cur_email" > "$CURRENT_FILE"
fi
fi
# Фоновый процесс: логин нового аккаунта + автосохранение после успеха.
# claude auth login ждёт авторизации в браузере и завершается после неё,
# затем определяем email нового аккаунта по токену (через API) и сохраняем.
(
claude auth login --claudeai </dev/null >/tmp/claude-add-account.log 2>&1
new_email=$(bash "$EMAIL_HELPER" "$CREDS" 2>/dev/null)
if [ -n "$new_email" ] && [ -f "$CREDS" ]; then
cp "$CREDS" "$ACCOUNTS_DIR/${new_email}.credentials.json"
chmod 600 "$ACCOUNTS_DIR/${new_email}.credentials.json"
echo "$new_email" > "$CURRENT_FILE"
echo "SAVED: $new_email" >> /tmp/claude-add-account.log
fi
) &
disown
# exit 0: Claude загружает скилл add-account и говорит что делать
exit 0
;;
kimi)
KEYS_DIR="$HOME/.config/ai-setup/kimi_keys"
CURRENT_FILE="$KEYS_DIR/current"
mkdir -p "$KEYS_DIR"
# Убедиться, что текущий ключ сохранён под своим alias.
current=$(cat "$CURRENT_FILE" 2>/dev/null || true)
if [ -n "$current" ] && [ -f "$KEYS_DIR/${current}.key" ]; then
chmod 600 "$KEYS_DIR/${current}.key"
fi
# Ключ передаётся в том же сообщении: /add-account <key>
new_key=$(echo "$prompt" | sed 's|^[[:space:]]*/add-account[[:space:]]*||; s|[[:space:]]*$||')
if [ -z "$new_key" ]; then
echo "" >&2
echo "Укажите Kimi API ключ в том же сообщении: /add-account sk-..." >&2
exit 2
fi
# Проверка ключа.
echo -n "Проверяю Kimi ключ... " >&2
response=$(curl -s -w "\n%{http_code}" --max-time 15 \
"https://api.kimi.com/coding/v1/messages" \
-H "x-api-key: $new_key" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"kimi-k2.7","max_tokens":1,"messages":[{"role":"user","content":"hi"}]}' \
2>/dev/null || echo "000")
code=$(echo "$response" | tail -1)
case "$code" in
200|400|429)
echo "OK" >&2
;;
401|403)
echo "" >&2
echo "Ошибка: ключ недействителен (HTTP $code)." >&2
exit 2
;;
000)
echo "" >&2
echo "Не удалось проверить ключ (сеть недоступна?). Попробуйте позже." >&2
exit 2
;;
*)
echo "" >&2
echo "Ошибка при проверке ключа (HTTP $code)." >&2
exit 2
;;
esac
# Генерация следующего свободного alias.
i=1
while [ -f "$KEYS_DIR/account${i}.key" ]; do
i=$((i + 1))
done
alias_name="account${i}"
echo "$new_key" > "$KEYS_DIR/${alias_name}.key"
chmod 600 "$KEYS_DIR/${alias_name}.key"
# Пытаемся получить email/имя аккаунта Kimi для статусной строки.
_kimi_account_info() {
local api_key="$1"
local resp email name
for url in "https://api.kimi.com/coding/v1/account" "https://api.kimi.com/coding/v1/users/me"; do
resp=$(curl -s --max-time 10 "$url" \
-H "x-api-key: $api_key" \
-H "Accept: application/json" \
2>/dev/null || echo "")
[ -z "$resp" ] && continue
email=$(echo "$resp" | jq -r '.email // .data.email // .account.email // empty' 2>/dev/null)
name=$(echo "$resp" | jq -r '.name // .data.name // .account.name // empty' 2>/dev/null)
if [ -n "$email" ]; then echo "$email"; return 0; fi
if [ -n "$name" ]; then echo "$name"; return 0; fi
done
return 1
}
meta=$(_kimi_account_info "$new_key" 2>/dev/null || true)
if [ -n "$meta" ]; then
echo "$meta" > "$KEYS_DIR/${alias_name}.meta"
chmod 600 "$KEYS_DIR/${alias_name}.meta"
fi
echo "$alias_name" > "$CURRENT_FILE"
echo "Новый Kimi ключ сохранён как: $alias_name. ai-kimi перезапустится с ним." >&2
exit 0
;;
*)
exit 0
;;
esac