refactor: switch ai-kimi to official Kimi API via Claude Code

- Replace native kimi CLI launcher with Claude Code + Kimi backend

- Update README description and permission flags

- Update test_isolated.sh and tests/test_fixes.sh for new ai-kimi logic
This commit is contained in:
Виталий Никитенко
2026-06-02 20:03:15 +07:00
parent 418a5ef6d5
commit 526b745cb3
4 changed files with 87 additions and 214 deletions

View File

@@ -549,182 +549,71 @@ chmod +x "$BIN_DIR/ai-deepseek"
# === ai-kimi ===
cat > "$BIN_DIR/ai-kimi" << 'KIMIEOF'
#!/usr/bin/env bash
# ai-kimi - запуск нативного Kimi Code через Artemox API
# ai-kimi - запуск Claude Code через официальный Kimi Code API
source ~/.local/bin/ai-api-helpers.sh
source "$HOME/.local/bin/ai-api-helpers.sh" 2>/dev/null || true
kimi_bin="$HOME/.kimi-code/bin/kimi"
[ ! -f "$kimi_bin" ] && kimi_bin="$(command -v kimi 2>/dev/null)"
if [ -z "$kimi_bin" ] || [ ! -f "$kimi_bin" ]; then
echo "Kimi Code не найден. Устанавливаю..."
curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash
kimi_bin="$HOME/.kimi-code/bin/kimi"
[ ! -f "$kimi_bin" ] && kimi_bin="$(command -v kimi 2>/dev/null)"
fi
if [ -z "$kimi_bin" ] || [ ! -f "$kimi_bin" ]; then
echo "Ошибка: не удалось установить Kimi Code."
exit 1
fi
case "${1:-}" in
--version|-V|--help|-h)
exec "$kimi_bin" "$@"
;;
esac
config_file="${KIMI_CODE_HOME:-$HOME/.kimi-code}/config.toml"
key_file="$HOME/.config/ai-setup/kimi_key"
model_alias="artemox/kimi-k2.6"
model_name="kimi-k2.6"
base_url="https://api.artemox.com/v1"
api_key=""
reauth=0
_extract_artemox_key() {
[ -f "$config_file" ] || return 0
python3 - "$config_file" <<'PYEOF'
import re
import sys
[ -f "$key_file" ] && api_key=$(cat "$key_file")
path = sys.argv[1]
try:
lines = open(path, encoding="utf-8").read().splitlines()
except OSError:
raise SystemExit(0)
inside = False
for line in lines:
stripped = line.strip()
if re.match(r'^\[providers\.(?:"artemox"|artemox)\]$', stripped):
inside = True
continue
if inside and stripped.startswith("["):
inside = False
if inside:
match = re.match(r'^api_key\s*=\s*"(.*)"\s*$', stripped)
if match:
print(match.group(1))
break
PYEOF
}
_write_artemox_config() {
mkdir -p "$(dirname "$config_file")"
ARTEMOX_API_KEY="$api_key" python3 - "$config_file" <<'PYEOF'
import json
import os
import re
import sys
path = sys.argv[1]
api_key = os.environ["ARTEMOX_API_KEY"]
try:
content = open(path, encoding="utf-8").read()
except OSError:
content = ""
lines = content.splitlines()
filtered = []
skip = False
for line in lines:
stripped = line.strip()
if re.match(r'^\[providers\.(?:"artemox"|artemox)\]$', stripped):
skip = True
continue
if re.match(r'^\[models\."artemox/kimi-k2\.6"\]$', stripped):
skip = True
continue
if skip and stripped.startswith("["):
skip = False
if skip:
continue
if re.match(r'^\s*default_model\s*=', line):
continue
filtered.append(line)
body = "\n".join(filtered).strip()
managed = f'''default_model = "artemox/kimi-k2.6"
# Managed by ai-kimi. Re-run ai-kimi to refresh Artemox settings.
[providers.artemox]
type = "openai"
base_url = "https://api.artemox.com/v1"
api_key = {json.dumps(api_key)}
[models."artemox/kimi-k2.6"]
provider = "artemox"
model = "kimi-k2.6"
max_context_size = 262144
capabilities = ["thinking", "tool_use"]
'''
new_content = managed
if body:
new_content += "\n" + body + "\n"
with open(path, "w", encoding="utf-8") as fh:
fh.write(new_content)
PYEOF
chmod 600 "$config_file"
}
_prompt_artemox_key() {
echo "Получить/проверить ключ: https://artemox.com/dashboard"
if [ ! -t 0 ]; then
echo "Artemox API ключ не найден. Запустите ai-kimi в интерактивном терминале и введите ключ."
if [ -n "$api_key" ]; then
echo -n "Проверка сохранённого Kimi ключа... "
_claude_test_api "https://api.kimi.com/coding/v1/messages" "x-api-key: $api_key" "kimi-k2.6"
_handle_api_response "Kimi" "$_CLAUDE_TEST_CODE" "$_CLAUDE_TEST_BODY" "Пополните баланс: https://www.kimi.com/code"
ret=$?
if [ $ret -eq 401 ]; then
rm -f "$key_file"
api_key=""
reauth=1
elif [ $ret -eq 429 ]; then
echo -n "Продолжить всё равно? (запросы могут не проходить) [y/N] "
read -r _ans; case "${_ans:-N}" in [Yy]*) ;; *) exit 1 ;; esac
elif [ $ret -ne 0 ]; then
exit 1
fi
read -r -p "Введите ваш Artemox API ключ: " api_key
[ -z "$api_key" ] && { echo "Выход."; exit 1; }
}
api_key=""
[ -f "$key_file" ] && api_key=$(cat "$key_file")
[ -z "$api_key" ] && api_key=$(_extract_artemox_key)
[ -z "$api_key" ] && _prompt_artemox_key
if declare -F _claude_test_openai_api >/dev/null && declare -F _handle_openai_api_response >/dev/null; then
echo -n "Проверка Artemox ключа... "
_claude_test_openai_api "$base_url/chat/completions" "$api_key" "$model_name"
_handle_openai_api_response "Artemox/Kimi" "$_CLAUDE_TEST_CODE" "$_CLAUDE_TEST_BODY" "Пополните баланс: https://artemox.com/dashboard"
case "$_CLAUDE_TEST_CODE" in
200|000)
;;
401|403)
rm -f "$key_file"
api_key=""
echo "Сохранённый Artemox ключ недействителен."
_prompt_artemox_key
echo -n "Повторная проверка Artemox ключа... "
_claude_test_openai_api "$base_url/chat/completions" "$api_key" "$model_name"
_handle_openai_api_response "Artemox/Kimi" "$_CLAUDE_TEST_CODE" "$_CLAUDE_TEST_BODY" "Пополните баланс: https://artemox.com/dashboard"
case "$_CLAUDE_TEST_CODE" in
200|000) ;;
*) echo "Ключ НЕ сохранён."; exit 1 ;;
esac
;;
429)
echo -n "Продолжить всё равно? (запросы могут не проходить) [y/N] "
read -r _ans
case "${_ans:-N}" in [Yy]*) ;; *) exit 1 ;; esac
;;
*)
echo "Ключ НЕ сохранён."
exit 1
;;
esac
fi
mkdir -p "$(dirname "$key_file")"
echo "$api_key" > "$key_file"
chmod 600 "$key_file"
_write_artemox_config
echo "Kimi настроен на Artemox: $model_alias"
if [ -z "$api_key" ] && [ "$reauth" -eq 1 ]; then
echo -n "Хотите ввести новый Kimi ключ? [Y/n] "
read -r _ans; case "${_ans:-Y}" in [Yy]*) ;; *) exit 1 ;; esac
fi
_build_ai_sys_prompt > /dev/null # сохраняет в ~/.kimi-code/AGENTS.md (kimi читает авто)
exec "$kimi_bin" --yolo "$@"
if [ -z "$api_key" ]; then
echo "Получить ключ: https://www.kimi.com/code"
read -r -p "Введите ваш Kimi API ключ: " api_key
[ -z "$api_key" ] && { echo "Выход."; exit 1; }
echo -n "Проверяю ключ и баланс... "
_claude_test_api "https://api.kimi.com/coding/v1/messages" "x-api-key: $api_key" "kimi-k2.6"
_handle_api_response "Kimi" "$_CLAUDE_TEST_CODE" "$_CLAUDE_TEST_BODY" "Пополните баланс: https://www.kimi.com/code"
ret=$?
if [ $ret -eq 0 ] || [ $ret -eq 429 ]; then
mkdir -p "$(dirname "$key_file")"
echo "$api_key" > "$key_file"
chmod 600 "$key_file"
echo "Ключ сохранён."
if [ $ret -eq 429 ]; then
echo -n "Продолжить всё равно? (запросы могут не проходить) [y/N] "
read -r _ans; case "${_ans:-N}" in [Yy]*) ;; *) exit 1 ;; esac
fi
else
echo "Ключ НЕ сохранён."
exit 1
fi
fi
SYS_PROMPT=$(_build_ai_sys_prompt)
ANTHROPIC_BASE_URL=https://api.kimi.com/coding \
ANTHROPIC_AUTH_TOKEN="$api_key" \
ANTHROPIC_MODEL=kimi-k2.6 \
ANTHROPIC_DEFAULT_OPUS_MODEL=kimi-k2.6 \
ANTHROPIC_DEFAULT_SONNET_MODEL=kimi-k2.6 \
ANTHROPIC_DEFAULT_HAIKU_MODEL=kimi-k2.6 \
CLAUDE_CODE_SUBAGENT_MODEL=kimi-k2.6 \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
claude --dangerously-skip-permissions --system-prompt "$SYS_PROMPT" "$@"
KIMIEOF
chmod +x "$BIN_DIR/ai-kimi"
@@ -795,7 +684,7 @@ echo "Доступные команды (теперь это независим
echo -e " ${CYAN}ai-claude${NC} - Оригинальный Claude Code (Anthropic)"
echo -e " ${CYAN}ai-gpt${NC} - OpenAI Codex (нативный CLI, автоустановка)"
echo -e " ${CYAN}ai-deepseek${NC} - DeepSeek (API ключ сохраняется)"
echo -e " ${CYAN}ai-kimi${NC} - Kimi K2.6 (нативный CLI, автоустановка)"
echo -e " ${CYAN}ai-kimi${NC} - Kimi K2.6 (через Claude Code, API ключ сохраняется)"
echo -e " ${CYAN}ai-gemini${NC} - Gemini (нативный agy CLI, автоустановка)"
echo ""
echo -e "${YELLOW}⚠️ Для Gemini используйте отдельный Google-аккаунт!${NC}"