#!/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 /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 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