feat(mimo): add ai-mimo launcher for Xiaomi MiMo V2.6 Pro

ai-mimo runs Claude Code through Xiaomi's Anthropic-compatible API
(Token Plan or pay-as-you-go). The key's endpoint is found by probing
token-plan-sgp, token-plan-ams and api.xiaomimimo.com (a key only works
in its own region) and is saved to mimo_base_url; MIMO_BASE_URL
overrides. Unreachable endpoints are skipped, token-plan-cn is left out
of the probe since it times out from our network, and a 402 on the
pay-as-you-go endpoint explains that a tp- Token Plan key is needed.

Always the smartest model: mimo-v2.6-pro in every slot and for
subagents, --model opus and --effort max on each start, 128000 output
tokens (Claude Code's ceiling), real 1M context window. Measured on
13.10: MiMo ignores output_config.effort (even "bogus" is accepted, no
length trend from low to max) and treats thinking adaptive like
enabled, so reasoning is always on; EFFORT_MAPPING.md records this.

/logout-mimo is registered as a command and handled by the logout hook
(removes mimo_key and mimo_base_url). setup.sh status, statusline brand
color, README, QUICK_START and AGENTS.md list the new launcher.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Виталий Никитенко
2026-10-13 15:43:25 +07:00
parent 6c507b4549
commit e6fe58eb37
9 changed files with 357 additions and 15 deletions

View File

@@ -1995,6 +1995,192 @@ claude --dangerously-skip-permissions --effort "${AI_EFFORT:-max}" --system-prom
ELTEXQWENEOF
chmod +x "$BIN_DIR/ai-eltex-qwen"
# === ai-mimo ===
cat > "$BIN_DIR/ai-mimo" << 'MIMOEOF'
#!/usr/bin/env bash
# ai-mimo - запуск Claude Code через Xiaomi MiMo V2.6 (Anthropic-compatible API, Token Plan)
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/ai-api-helpers.sh" 2>/dev/null || true
key_file="$HOME/.config/ai-setup/mimo_key"
url_file="$HOME/.config/ai-setup/mimo_base_url"
api_key=""
reauth=0
# Принудительный сброс сохранённого ключа через AI_RESET_KEY=1
if [ "${AI_RESET_KEY:-0}" == "1" ]; then
rm -f "$key_file" "$url_file"
fi
[ -f "$key_file" ] && api_key=$(cat "$key_file")
# Ключ Token Plan (tp-...) работает только на эндпоинте региона подписки (sgp/ams/cn),
# ключ pay-as-you-go (sk-...) - на api.xiaomimimo.com. Эндпоинт находим перебором при
# проверке ключа и запоминаем в mimo_base_url; MIMO_BASE_URL перебивает.
mimo_base_url="${MIMO_BASE_URL:-}"
[ -z "$mimo_base_url" ] && [ -f "$url_file" ] && mimo_base_url=$(cat "$url_file")
# _mimo_check_key: 1-токенный запрос с ключом $1. Без известного эндпоинта перебирает
# регионы: чужой регион отвечает 401/403, первый другой ответ задаёт mimo_base_url.
# Недоступный эндпоинт (код 000*: _claude_test_api при сетевой ошибке отдаёт 000000)
# пропускаем. token-plan-cn в переборе нет: с наших машин он не отвечает (таймаут 15 с),
# для него MIMO_BASE_URL=https://token-plan-cn.xiaomimimo.com/anthropic.
# Bearer, как у Claude Code с ANTHROPIC_AUTH_TOKEN.
_mimo_check_key() {
local url auth_code="" auth_body=""
if [ -n "$mimo_base_url" ]; then
_claude_test_api "$mimo_base_url/v1/messages" "Authorization: Bearer $1" "mimo-v2.6-flash"
return
fi
for url in https://token-plan-sgp.xiaomimimo.com/anthropic \
https://token-plan-ams.xiaomimimo.com/anthropic \
https://api.xiaomimimo.com/anthropic; do
_claude_test_api "$url/v1/messages" "Authorization: Bearer $1" "mimo-v2.6-flash"
case "$_CLAUDE_TEST_CODE" in
401|403) auth_code="$_CLAUDE_TEST_CODE"; auth_body="$_CLAUDE_TEST_BODY" ;;
000*) ;;
*) mimo_base_url="$url"; return ;;
esac
done
# Ни один эндпоинт не принял ключ. Отказ в авторизации разберёт _handle_api_response,
# а без сети эндпоинт не узнать и запускать Claude Code некуда.
if [ -n "$auth_code" ]; then
_CLAUDE_TEST_CODE="$auth_code"
_CLAUDE_TEST_BODY="$auth_body"
return
fi
echo ""
echo -e "\033[0;31m[СЕТЬ]\033[0m Эндпоинты MiMo недоступны, ключ не проверен."
echo " Задай эндпоинт явно: MIMO_BASE_URL=https://token-plan-sgp.xiaomimimo.com/anthropic ai-mimo"
exit 1
}
# _mimo_check_result: разбор ответа проверки. 402 на pay-as-you-go эндпоинте значит ключ
# sk-... с нулевым балансом: подписку Token Plan он не тратит, для неё свой ключ tp-...
_mimo_check_result() {
_handle_api_response "MiMo" "$_CLAUDE_TEST_CODE" "$_CLAUDE_TEST_BODY" "Лимит Token Plan: https://platform.xiaomimimo.com"
if [ "$_API_RET" = "402" ] && [ "$mimo_base_url" = "https://api.xiaomimimo.com/anthropic" ]; then
echo " Это ключ pay-as-you-go (sk-...), подписку Token Plan он не использует."
echo " Для Token Plan создай ключ на странице Token Plan: Dedicated API Key -> Create API Key (tp-...)."
fi
}
if [ -n "$api_key" ]; then
echo -n "Проверка сохранённого MiMo ключа... "
_mimo_check_key "$api_key"
_mimo_check_result
ret=$_API_RET
if [ $ret -eq 401 ]; then
rm -f "$key_file" "$url_file"
api_key=""
mimo_base_url="${MIMO_BASE_URL:-}"
reauth=1
elif [ $ret -eq 429 ]; then
echo -n "Продолжить всё равно? (запросы могут не проходить) [y/N] "
read -r _ans
case "${_ans:-N}" in
[Yy]*) ;;
*)
echo -n "Хотите ввести новый MiMo ключ? [Y/n] "
read -r _ans2
case "${_ans2:-Y}" in
[Yy]*)
rm -f "$key_file" "$url_file"
api_key=""
mimo_base_url="${MIMO_BASE_URL:-}"
reauth=1
;;
*) exit 1 ;;
esac
;;
esac
elif [ $ret -ne 0 ]; then
exit 1
fi
fi
if [ -z "$api_key" ] && [ "$reauth" -eq 1 ]; then
echo -n "Хотите ввести новый MiMo ключ? [Y/n] "
read -r _ans; case "${_ans:-Y}" in [Yy]*) ;; *) exit 1 ;; esac
fi
if [ -z "$api_key" ]; then
echo "Получить ключ: https://platform.xiaomimimo.com (Token Plan - tp-..., pay-as-you-go - sk-...)"
read -r -p "Введите ваш Xiaomi MiMo API ключ: " api_key
[ -z "$api_key" ] && { echo "Выход."; exit 1; }
echo -n "Проверяю ключ... "
_mimo_check_key "$api_key"
_mimo_check_result
ret=$_API_RET
if [ $ret -eq 0 ] || [ $ret -eq 429 ]; then
mkdir -p "$(dirname "$key_file")"
echo "$api_key" > "$key_file"
echo "$mimo_base_url" > "$url_file"
chmod 600 "$key_file" "$url_file"
echo "Ключ сохранён (эндпоинт: $mimo_base_url)."
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
_PROMPT_FILE=$(mktemp /tmp/ai-sys-prompt.XXXXXX)
trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM
_build_ai_sys_prompt > "$_PROMPT_FILE"
export AI_LAUNCHER=mimo
export CLAUDE_CONFIG_DIR="$HOME/.config/ai-setup/cfg/mimo"
# Модель: всегда самая умная MiMo - mimo-v2.6-pro во всех трёх слотах и в сабагентах, как
# у ai-glm. Flash не используем: ai-mimo задуман как максимум качества, а не экономия
# кредитов. pro-ultraspeed - тот же Pro, только быстрее и в ~10 раз дороже.
# mimo-v2.5-pro/mimo-v2.5 сняты 21.10.2026 (с 14.10 их роутят на v2.6-pro/v2.6-flash):
# https://mimo.mi.com/docs/en-US/updates/deprecate
# availableModels НЕ задаём (он схлопывает пикер). --model opus при каждом запуске: выбор
# через /model живёт до конца сессии, следующий запуск снова на Pro.
# CLAUDE_CODE_MAX_CONTEXT_TOKENS: mimo-* нет в реестре моделей Claude Code, без env окно
# считалось бы = 200K (ctx: врал бы в ~5 раз, автокомпакт жал бы сессию). У Pro реальное
# окно 1M, поэтому CLAUDE_CODE_DISABLE_1M_CONTEXT не выставляем.
# CLAUDE_CODE_MAX_OUTPUT_TOKENS=128000: потолок Claude Code (131072 он режет до 128000),
# MiMo V2.6 отдаёт до 131072. По умолчанию незнакомой модели досталось бы 32000 на
# размышления + ответ.
# Размышления: MiMo думает всегда. Claude Code шлёт thinking adaptive, а MiMo отрабатывает
# его так же, как enabled (замер 13.10: даже на "скажи привет" есть thinking, длина та же).
# Effort MiMo игнорирует: Claude Code шлёт output_config.effort (и без
# CLAUDE_CODE_ALWAYS_ENABLE_EFFORT), MiMo принимает даже effort=bogus, а длина размышлений
# от low до max не меняется (см. EFFORT_MAPPING.md). Стартуем на max через CLI --effort,
# как ai-eltex-qwen: если Xiaomi начнёт его учитывать, будет максимум.
_setup_isolated_config mimo opus high ''
# /logout-mimo: без зарегистрированной команды Claude Code отвечает "Unknown command" и
# не зовёт UserPromptSubmit-хук (см. ai-eltex).
mkdir -p "$CLAUDE_CONFIG_DIR/commands"
cat > "$CLAUDE_CONFIG_DIR/commands/logout-mimo.md" <<'CMDEOF'
---
description: Удалить сохранённый ключ ai-mimo (обрабатывает хук, без LLM)
---
Хук не сработал: удали ~/.config/ai-setup/mimo_key вручную и перезапусти ai-mimo (или запусти AI_RESET_KEY=1 ai-mimo).
CMDEOF
ANTHROPIC_BASE_URL="$mimo_base_url" \
ANTHROPIC_AUTH_TOKEN="$api_key" \
ANTHROPIC_DEFAULT_OPUS_MODEL=mimo-v2.6-pro \
ANTHROPIC_DEFAULT_OPUS_MODEL_NAME="MiMo V2.6 Pro" \
ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION="Xiaomi MiMo V2.6 Pro - флагман для сложных задач" \
ANTHROPIC_DEFAULT_SONNET_MODEL=mimo-v2.6-pro \
ANTHROPIC_DEFAULT_SONNET_MODEL_NAME="MiMo V2.6 Pro" \
ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION="Xiaomi MiMo V2.6 Pro - флагман для сложных задач" \
ANTHROPIC_DEFAULT_HAIKU_MODEL=mimo-v2.6-pro \
ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME="MiMo V2.6 Pro" \
ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION="Xiaomi MiMo V2.6 Pro - флагман для сложных задач" \
CLAUDE_CODE_SUBAGENT_MODEL=mimo-v2.6-pro \
CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000 \
CLAUDE_CODE_MAX_OUTPUT_TOKENS=128000 \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
claude --dangerously-skip-permissions --model opus --effort "${AI_EFFORT:-max}" --system-prompt-file "$_PROMPT_FILE" "$@"
MIMOEOF
chmod +x "$BIN_DIR/ai-mimo"
# === ai-openrouter ===
cat > "$BIN_DIR/ai-openrouter" << 'OPENROUTEREOF'
#!/usr/bin/env bash
@@ -2298,6 +2484,7 @@ _setup_isolated_config kimi opus high ''
_setup_isolated_config glm opus xhigh ''
_setup_isolated_config eltex opus xhigh ''
_setup_isolated_config eltex-qwen opus high ''
_setup_isolated_config mimo opus high ''
_setup_isolated_config openrouter "openai/gpt-5.5" high ''
_setup_isolated_config opencode deepseek-v4-pro high ''
@@ -2308,7 +2495,7 @@ rm -f "$BIN_DIR/claude_gpt" "$BIN_DIR/claude_deepseek" "$BIN_DIR/claude_kimi" "$
if [ "$BIN_DIR" != "$HOME/.local/bin" ]; then
warn "BIN_DIR=$BIN_DIR — удаляю старые скрипты из ~/.local/bin/ ..."
rm -f "$HOME/.local/bin/ai-gpt" "$HOME/.local/bin/ai-deepseek" "$HOME/.local/bin/ai-kimi" \
"$HOME/.local/bin/ai-glm" "$HOME/.local/bin/ai-eltex" "$HOME/.local/bin/ai-eltex-qwen" "$HOME/.local/bin/ai-openrouter" "$HOME/.local/bin/ai-gemini" "$HOME/.local/bin/ai-cursor" "$HOME/.local/bin/ai-claude" \
"$HOME/.local/bin/ai-glm" "$HOME/.local/bin/ai-eltex" "$HOME/.local/bin/ai-eltex-qwen" "$HOME/.local/bin/ai-mimo" "$HOME/.local/bin/ai-openrouter" "$HOME/.local/bin/ai-gemini" "$HOME/.local/bin/ai-cursor" "$HOME/.local/bin/ai-claude" \
"$HOME/.local/bin/ai-opencode" \
"$HOME/.local/bin/ai-api-helpers.sh" "$HOME/.local/bin/claude-gpt-effort-proxy.py"
fi
@@ -2330,6 +2517,7 @@ echo -e " ${CYAN}ai-kimi${NC} - Kimi K2.7 Code (через Claude
echo -e " ${CYAN}ai-glm${NC} - GLM 5.3 (через Claude Code, Zhipu AI API)"
echo -e " ${CYAN}ai-eltex${NC} - Корпоративный LLM-прокси Eltex (через Claude Code, ключ от админов)"
echo -e " ${CYAN}ai-eltex-qwen${NC} - Корпоративный LLM-прокси Eltex, модели Qwen (через Claude Code, свой ключ)"
echo -e " ${CYAN}ai-mimo${NC} - Xiaomi MiMo V2.6 Pro, максимум рассуждений (через Claude Code, Token Plan)"
echo -e " ${CYAN}ai-openrouter${NC} - OpenRouter (через Claude Code: GPT-5.5, Grok, Qwen, GLM 5.2 и др.)"
echo -e " ${CYAN}ai-opencode${NC} - OpenCode Go (через Claude Code + routatic-proxy: DeepSeek, Kimi, Qwen, GLM, MiniMax, MiMo)"
echo ""