Compare commits
2 Commits
60b915de5f
...
4331ebb675
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4331ebb675 | ||
|
|
8c7c2e9e0f |
@@ -4,6 +4,12 @@ input=$(cat)
|
|||||||
cwd=$(echo "$input" | jq -r '.cwd')
|
cwd=$(echo "$input" | jq -r '.cwd')
|
||||||
model=$(echo "$input" | jq -r '.model.display_name // empty')
|
model=$(echo "$input" | jq -r '.model.display_name // empty')
|
||||||
model_id=$(echo "$input" | jq -r '.model.id // empty')
|
model_id=$(echo "$input" | jq -r '.model.id // empty')
|
||||||
|
# Суффикс [1m] в отображении не нужен: окно контекста задаётся
|
||||||
|
# CLAUDE_CODE_MAX_CONTEXT_TOKENS, а не суффиксом модели
|
||||||
|
model="${model/\[1m\]/}"
|
||||||
|
model="${model% \[1M\]}"
|
||||||
|
model="${model% (1M context)}"
|
||||||
|
model_id="${model_id/\[1m\]/}"
|
||||||
five_pct=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
|
five_pct=$(echo "$input" | jq -r '.rate_limits.five_hour.used_percentage // empty')
|
||||||
five_reset=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
|
five_reset=$(echo "$input" | jq -r '.rate_limits.five_hour.resets_at // empty')
|
||||||
week_pct=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
|
week_pct=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
|
||||||
@@ -11,15 +17,18 @@ week_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')
|
|||||||
ctx_pct=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
|
ctx_pct=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
|
||||||
|
|
||||||
|
|
||||||
|
# Разделитель сегментов: жирная серая средняя точка ·
|
||||||
|
_sep() { printf " \033[1m\033[38;5;240m·\033[00m "; }
|
||||||
|
|
||||||
# Цвет effort: насыщенные, глубже чем пастельные (jewel tones)
|
# Цвет effort: насыщенные, глубже чем пастельные (jewel tones)
|
||||||
_effort_color() {
|
_effort_color() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
low) printf '\033[38;5;220m[low]\033[00m' ;; # золотой
|
low) printf '\033[38;5;220mlow\033[00m' ;; # золотой
|
||||||
medium) printf '\033[38;5;50m[medium]\033[00m' ;; # насыщенный teal
|
medium) printf '\033[38;5;50mmedium\033[00m' ;; # насыщенный teal
|
||||||
high) printf '\033[38;5;38m[high]\033[00m' ;; # глубокий голубой
|
high) printf '\033[38;5;38mhigh\033[00m' ;; # глубокий голубой
|
||||||
xhigh) printf '\033[38;5;206m[xhigh]\033[00m' ;; # насыщенный фиолетовый
|
xhigh) printf '\033[38;5;206mxhigh\033[00m' ;; # насыщенный фиолетовый
|
||||||
max) printf '\033[38;5;210m[\033[38;5;220mm\033[38;5;114ma\033[38;5;50mx\033[38;5;206m]\033[00m' ;; # радуга
|
max) printf '\033[38;5;220mm\033[38;5;114ma\033[38;5;50mx\033[38;5;206m\033[00m' ;; # радуга
|
||||||
*) printf '\033[38;5;252m[%s]\033[00m' "$1" ;;
|
*) printf '\033[38;5;252m%s\033[00m' "$1" ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +38,7 @@ _brand_color() {
|
|||||||
deepseek) printf '\033[38;5;69m' ;; # DeepSeek фирменный синий
|
deepseek) printf '\033[38;5;69m' ;; # DeepSeek фирменный синий
|
||||||
claude) printf '\033[38;5;173m' ;; # Anthropic оранжевый
|
claude) printf '\033[38;5;173m' ;; # Anthropic оранжевый
|
||||||
kimi) printf '\033[38;5;81m' ;; # Kimi голубой
|
kimi) printf '\033[38;5;81m' ;; # Kimi голубой
|
||||||
|
glm) printf '\033[38;5;223m' ;; # Z.ai кремовый (бренд-фон z.ai, #FFE4B5)
|
||||||
openrouter) printf '\033[38;5;135m' ;; # OpenRouter фиолетовый
|
openrouter) printf '\033[38;5;135m' ;; # OpenRouter фиолетовый
|
||||||
*) printf '\033[38;5;223m' ;; # кремовый (fallback)
|
*) printf '\033[38;5;223m' ;; # кремовый (fallback)
|
||||||
esac
|
esac
|
||||||
@@ -39,7 +49,7 @@ branch=$(git -C "$cwd" --no-optional-locks symbolic-ref --short HEAD 2>/dev/null
|
|||||||
short_cwd="${cwd/#$HOME/\~}"
|
short_cwd="${cwd/#$HOME/\~}"
|
||||||
printf "\033[38;5;252m%s\033[00m" "$short_cwd"
|
printf "\033[38;5;252m%s\033[00m" "$short_cwd"
|
||||||
|
|
||||||
[ -n "$branch" ] && printf " \033[38;5;252m[%s]\033[00m" "$branch"
|
[ -n "$branch" ] && { _sep; printf "\033[38;5;111m%s\033[00m" "$branch"; }
|
||||||
if [ -n "$model" ]; then
|
if [ -n "$model" ]; then
|
||||||
brand_color=$(_brand_color "${AI_LAUNCHER:-}")
|
brand_color=$(_brand_color "${AI_LAUNCHER:-}")
|
||||||
effort=$(echo "$input" | jq -r ".effort.level // empty")
|
effort=$(echo "$input" | jq -r ".effort.level // empty")
|
||||||
@@ -84,19 +94,21 @@ if [ -n "$model" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
[ -n "$account" ] && printf " %s[%s]\033[00m" "$brand_color" "$account"
|
[ -n "$account" ] && { _sep; printf "%s%s\033[00m" "$brand_color" "$account"; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Аккаунт/ключ Kimi — показываем alias (account1/account2/...).
|
# Аккаунт/ключ Kimi — показываем alias (account1/account2/...).
|
||||||
if [ "${AI_LAUNCHER:-}" = "kimi" ]; then
|
if [ "${AI_LAUNCHER:-}" = "kimi" ]; then
|
||||||
kimi_account=$(cat "$HOME/.config/ai-setup/kimi_keys/current" 2>/dev/null)
|
kimi_account=$(cat "$HOME/.config/ai-setup/kimi_keys/current" 2>/dev/null)
|
||||||
[ -n "$kimi_account" ] && printf " %s[%s]\033[00m" "$brand_color" "$kimi_account"
|
[ -n "$kimi_account" ] && { _sep; printf "%s%s\033[00m" "$brand_color" "$kimi_account"; }
|
||||||
fi
|
fi
|
||||||
if [ -n "$effort" ]; then
|
if [ -n "$effort" ]; then
|
||||||
printf " %s%s " "$brand_color" "$model"
|
_sep
|
||||||
|
printf "%s%s " "$brand_color" "$model"
|
||||||
_effort_color "$effort"
|
_effort_color "$effort"
|
||||||
else
|
else
|
||||||
printf " %s%s\033[00m" "$brand_color" "$model"
|
_sep
|
||||||
|
printf "%s%s\033[00m" "$brand_color" "$model"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -138,7 +150,7 @@ if [[ "$model_id" == *deepseek* ]]; then
|
|||||||
cache_file="$HOME/.cache/ai-setup/deepseek_balance"
|
cache_file="$HOME/.cache/ai-setup/deepseek_balance"
|
||||||
if [ -f "$cache_file" ]; then
|
if [ -f "$cache_file" ]; then
|
||||||
balance=$(head -1 "$cache_file")
|
balance=$(head -1 "$cache_file")
|
||||||
[ -n "$balance" ] && printf " \033[38;5;78m%s\033[00m" "$balance"
|
[ -n "$balance" ] && { _sep; printf "\033[38;5;78m%s\033[00m" "$balance"; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Фоновое обновление баланса (не чаще раза в 30 секунд)
|
# Фоновое обновление баланса (не чаще раза в 30 секунд)
|
||||||
@@ -182,7 +194,7 @@ elif [ "${AI_LAUNCHER:-}" = "openrouter" ]; then
|
|||||||
cache_file="$HOME/.cache/ai-setup/openrouter_balance"
|
cache_file="$HOME/.cache/ai-setup/openrouter_balance"
|
||||||
if [ -f "$cache_file" ]; then
|
if [ -f "$cache_file" ]; then
|
||||||
balance=$(head -1 "$cache_file")
|
balance=$(head -1 "$cache_file")
|
||||||
[ -n "$balance" ] && printf " \033[38;5;78m%s\033[00m" "$balance"
|
[ -n "$balance" ] && { _sep; printf "\033[38;5;78m%s\033[00m" "$balance"; }
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Фоновое обновление баланса (не чаще раза в 30 секунд)
|
# Фоновое обновление баланса (не чаще раза в 30 секунд)
|
||||||
@@ -247,13 +259,13 @@ else
|
|||||||
five_int=$(printf '%.0f' "$five_pct")
|
five_int=$(printf '%.0f' "$five_pct")
|
||||||
remaining=$(fmt_remaining "$five_reset")
|
remaining=$(fmt_remaining "$five_reset")
|
||||||
color=$(pct_color "$five_int")
|
color=$(pct_color "$five_int")
|
||||||
printf " %s%s:%s%%\033[00m" "$color" "$remaining" "$five_int"
|
_sep; printf "%s%s:%s%%\033[00m" "$color" "$remaining" "$five_int"
|
||||||
fi
|
fi
|
||||||
if [ -n "$week_pct" ] && [ -n "$week_reset" ]; then
|
if [ -n "$week_pct" ] && [ -n "$week_reset" ]; then
|
||||||
week_int=$(printf '%.0f' "$week_pct")
|
week_int=$(printf '%.0f' "$week_pct")
|
||||||
remaining=$(fmt_remaining "$week_reset")
|
remaining=$(fmt_remaining "$week_reset")
|
||||||
color=$(pct_color "$week_int")
|
color=$(pct_color "$week_int")
|
||||||
printf " %s%s:%s%%\033[00m" "$color" "$remaining" "$week_int"
|
_sep; printf "%s%s:%s%%\033[00m" "$color" "$remaining" "$week_int"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -263,7 +275,7 @@ fi
|
|||||||
if [ -n "$ctx_pct" ]; then
|
if [ -n "$ctx_pct" ]; then
|
||||||
ctx_int=$(printf '%.0f' "$ctx_pct")
|
ctx_int=$(printf '%.0f' "$ctx_pct")
|
||||||
color=$(pct_color "$ctx_int")
|
color=$(pct_color "$ctx_int")
|
||||||
printf " %sctx:%s%%\033[00m" "$color" "$ctx_int"
|
_sep; printf "%sctx:%s%%\033[00m" "$color" "$ctx_int"
|
||||||
|
|
||||||
# Звуковой сигнал при первом достижении 60%
|
# Звуковой сигнал при первом достижении 60%
|
||||||
alert_file="$HOME/.cache/ai-setup/ctx_alert_state"
|
alert_file="$HOME/.cache/ai-setup/ctx_alert_state"
|
||||||
|
|||||||
@@ -1243,7 +1243,9 @@ fi
|
|||||||
|
|
||||||
_build_ai_sys_prompt > /dev/null # сохраняет в ~/.codex/AGENTS.md (codex читает авто)
|
_build_ai_sys_prompt > /dev/null # сохраняет в ~/.codex/AGENTS.md (codex читает авто)
|
||||||
_setup_codex_sound_hooks
|
_setup_codex_sound_hooks
|
||||||
exec "$codex_bin" --dangerously-bypass-approvals-and-sandbox "$@"
|
exec "$codex_bin" --dangerously-bypass-approvals-and-sandbox \
|
||||||
|
-c 'tui.status_line=["model-with-reasoning","git-branch","context-used","five-hour-limit","current-dir"]' \
|
||||||
|
"$@"
|
||||||
GPTEOF
|
GPTEOF
|
||||||
chmod +x "$BIN_DIR/ai-gpt"
|
chmod +x "$BIN_DIR/ai-gpt"
|
||||||
|
|
||||||
@@ -1644,9 +1646,10 @@ trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM
|
|||||||
_build_ai_sys_prompt > "$_PROMPT_FILE"
|
_build_ai_sys_prompt > "$_PROMPT_FILE"
|
||||||
export AI_LAUNCHER=glm
|
export AI_LAUNCHER=glm
|
||||||
export CLAUDE_CONFIG_DIR="$HOME/.config/ai-setup/cfg/glm"
|
export CLAUDE_CONFIG_DIR="$HOME/.config/ai-setup/cfg/glm"
|
||||||
# Пикер: Opus/Sonnet = GLM 5.3, Haiku = GLM 5.3[1m]. availableModels НЕ задаём
|
# Пикер: все три слота = glm-5.3. availableModels НЕ задаём (он схлопывает пикер).
|
||||||
# (он схлопывает пикер). Claude Code навязывает 3 слота; незаданный показал бы
|
# Claude Code навязывает 3 слота; незаданный показал бы чужой Claude, поэтому
|
||||||
# чужой Claude, поэтому opus+sonnet = glm-5.3, haiku = glm-5.3[1m].
|
# opus+sonnet+haiku = glm-5.3. Окно контекста у всех слотов задаёт env
|
||||||
|
# CLAUDE_CODE_MAX_CONTEXT_TOKENS ниже — суффикс [1m] больше не нужен.
|
||||||
_setup_isolated_config glm opus high ''
|
_setup_isolated_config glm opus high ''
|
||||||
# ai-glm стартует на /effort max. max невалиден в settings.json (там только
|
# ai-glm стартует на /effort max. max невалиден в settings.json (там только
|
||||||
# low/medium/high/xhigh), поэтому задаём через CLI --effort, а не _apply_effort.
|
# low/medium/high/xhigh), поэтому задаём через CLI --effort, а не _apply_effort.
|
||||||
@@ -1657,6 +1660,10 @@ _setup_isolated_config glm opus high ''
|
|||||||
# а флаг заставлял бы счётчик ctx: считать окно = 200K (врал в ~5 раз). Прочие
|
# а флаг заставлял бы счётчик ctx: считать окно = 200K (врал в ~5 раз). Прочие
|
||||||
# лаунчеры (deepseek/kimi/openrouter/opencode) флаг оставляют — у них другой контекст
|
# лаунчеры (deepseek/kimi/openrouter/opencode) флаг оставляют — у них другой контекст
|
||||||
# и флаг убирает [1M]-дубли из пикера; ai-claude его и так не использует.
|
# и флаг убирает [1M]-дубли из пикера; ai-claude его и так не использует.
|
||||||
|
# CLAUDE_CODE_MAX_CONTEXT_TOKENS: glm-* нет в реестре моделей Claude Code, поэтому
|
||||||
|
# окно по умолчанию считается = 200K — ctx: врал бы в ~5 раз, а автокомпакт жал бы
|
||||||
|
# сессию в 200K. Задаём реальное окно 1M явно; env применяется к не-claude моделям
|
||||||
|
# независимо от суффикса, поэтому [1m] у Haiku-слота не нужен и убран.
|
||||||
ANTHROPIC_BASE_URL="$glm_base_url" \
|
ANTHROPIC_BASE_URL="$glm_base_url" \
|
||||||
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
||||||
ANTHROPIC_DEFAULT_OPUS_MODEL=glm-5.3 \
|
ANTHROPIC_DEFAULT_OPUS_MODEL=glm-5.3 \
|
||||||
@@ -1665,10 +1672,11 @@ ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION="GLM 5.3 — флагман Zhipu AI" \
|
|||||||
ANTHROPIC_DEFAULT_SONNET_MODEL=glm-5.3 \
|
ANTHROPIC_DEFAULT_SONNET_MODEL=glm-5.3 \
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL_NAME="GLM 5.3" \
|
ANTHROPIC_DEFAULT_SONNET_MODEL_NAME="GLM 5.3" \
|
||||||
ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION="GLM 5.3 — флагман Zhipu AI" \
|
ANTHROPIC_DEFAULT_SONNET_MODEL_DESCRIPTION="GLM 5.3 — флагман Zhipu AI" \
|
||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL='glm-5.3[1m]' \
|
ANTHROPIC_DEFAULT_HAIKU_MODEL=glm-5.3 \
|
||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME="GLM 5.3 [1M]" \
|
ANTHROPIC_DEFAULT_HAIKU_MODEL_NAME="GLM 5.3" \
|
||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION="GLM 5.3 [1M] — расширенный контекст" \
|
ANTHROPIC_DEFAULT_HAIKU_MODEL_DESCRIPTION="GLM 5.3 — флагман Zhipu AI" \
|
||||||
CLAUDE_CODE_SUBAGENT_MODEL=glm-5.3 \
|
CLAUDE_CODE_SUBAGENT_MODEL=glm-5.3 \
|
||||||
|
CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000 \
|
||||||
CLAUDE_CODE_ALWAYS_ENABLE_EFFORT=1 \
|
CLAUDE_CODE_ALWAYS_ENABLE_EFFORT=1 \
|
||||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
||||||
claude --dangerously-skip-permissions --effort "${AI_EFFORT:-max}" --system-prompt-file "$_PROMPT_FILE" "$@"
|
claude --dangerously-skip-permissions --effort "${AI_EFFORT:-max}" --system-prompt-file "$_PROMPT_FILE" "$@"
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ test_gpt_no_proxy() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── ai-gpt: informative Codex status line ───────────────────────────────────
|
||||||
|
test_gpt_status_line() {
|
||||||
|
if echo "$GPT_SECTION" | grep -Fq 'tui.status_line=["model-with-reasoning","git-branch","context-used","five-hour-limit","current-dir"]'; then
|
||||||
|
ok "ai-gpt: shows model, branch, context usage, primary limit, and directory"
|
||||||
|
else
|
||||||
|
fail "ai-gpt: missing configured Codex status line"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# ── ai-kimi: launches claude with Kimi backend ────────────────────────────
|
# ── ai-kimi: launches claude with Kimi backend ────────────────────────────
|
||||||
test_kimi_claude_launcher() {
|
test_kimi_claude_launcher() {
|
||||||
if echo "$KIMI_SECTION" | grep -q 'claude --dangerously-skip-permissions' \
|
if echo "$KIMI_SECTION" | grep -q 'claude --dangerously-skip-permissions' \
|
||||||
@@ -86,11 +95,12 @@ test_glm_claude_launcher() {
|
|||||||
test_glm_official_api() {
|
test_glm_official_api() {
|
||||||
if echo "$GLM_SECTION" | grep -q 'api.z.ai/api/anthropic' \
|
if echo "$GLM_SECTION" | grep -q 'api.z.ai/api/anthropic' \
|
||||||
&& echo "$GLM_SECTION" | grep -q 'ANTHROPIC_DEFAULT_OPUS_MODEL=glm-5.3' \
|
&& echo "$GLM_SECTION" | grep -q 'ANTHROPIC_DEFAULT_OPUS_MODEL=glm-5.3' \
|
||||||
&& echo "$GLM_SECTION" | grep -q "ANTHROPIC_DEFAULT_HAIKU_MODEL='glm-5.3\[1m\]'" \
|
&& echo "$GLM_SECTION" | grep -q 'ANTHROPIC_DEFAULT_HAIKU_MODEL=glm-5.3' \
|
||||||
|
&& echo "$GLM_SECTION" | grep -q 'CLAUDE_CODE_MAX_CONTEXT_TOKENS=1000000' \
|
||||||
&& echo "$GLM_SECTION" | grep -q 'x-api-key'; then
|
&& echo "$GLM_SECTION" | grep -q 'x-api-key'; then
|
||||||
ok "ai-glm: uses official Zhipu AI API (glm-5.3 opus/sonnet, glm-5.3[1m] haiku)"
|
ok "ai-glm: uses official Zhipu AI API (glm-5.3 everywhere, ctx window 1M via env)"
|
||||||
else
|
else
|
||||||
fail "ai-glm: must use official Zhipu AI API with glm-5.3 and x-api-key"
|
fail "ai-glm: must use official Zhipu AI API with glm-5.3, 1M context window and x-api-key"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +295,7 @@ test_add_hook_syntax() {
|
|||||||
test_script_syntax
|
test_script_syntax
|
||||||
test_gpt_autoinstall
|
test_gpt_autoinstall
|
||||||
test_gpt_no_proxy
|
test_gpt_no_proxy
|
||||||
|
test_gpt_status_line
|
||||||
test_kimi_claude_launcher
|
test_kimi_claude_launcher
|
||||||
test_kimi_official_api
|
test_kimi_official_api
|
||||||
test_kimi_no_artemox
|
test_kimi_no_artemox
|
||||||
|
|||||||
Reference in New Issue
Block a user