diff --git a/home-configs/claude/hooks/effort-save-hook.sh b/home-configs/claude/hooks/effort-save-hook.sh index 6705535..3d05366 100644 --- a/home-configs/claude/hooks/effort-save-hook.sh +++ b/home-configs/claude/hooks/effort-save-hook.sh @@ -4,17 +4,21 @@ launcher="${AI_LAUNCHER:-}" [ -z "$launcher" ] && exit 0 cat /dev/stdin > /dev/null 2>&1 # drain stdin (Claude Code передаёт JSON) -effort=$(python3 -c " -import json, os -p = os.path.expanduser('~/.claude/settings.json') -if os.path.exists(p): - try: - d = json.load(open(p)) - print(d.get('effortLevel', '')) - except Exception: - pass -" 2>/dev/null) -[ -z "$effort" ] && exit 0 mkdir -p "$HOME/.cache/ai-setup" -echo "$effort" > "$HOME/.cache/ai-setup/effort_${launcher}" +python3 - "$HOME/.claude/settings.json" "$HOME/.cache/ai-setup" "$launcher" <<'PYEOF' +import json, os, sys +settings_path, cache_dir, launcher = sys.argv[1], sys.argv[2], sys.argv[3] +if not os.path.exists(settings_path): + sys.exit(0) +try: + d = json.load(open(settings_path)) +except Exception: + sys.exit(0) +effort = d.get('effortLevel', '') +if effort: + open(os.path.join(cache_dir, f'effort_{launcher}'), 'w').write(effort) +model = d.get('model', '') +if model: + open(os.path.join(cache_dir, f'model_{launcher}'), 'w').write(model) +PYEOF exit 0 diff --git a/home-configs/claude/statusline-command.sh b/home-configs/claude/statusline-command.sh index 385f791..ab1e437 100755 --- a/home-configs/claude/statusline-command.sh +++ b/home-configs/claude/statusline-command.sh @@ -10,28 +10,40 @@ week_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty') ctx_pct=$(echo "$input" | jq -r '.context_window.used_percentage // empty') -# Цвет effort: мягкая гармоничная палитра +# Цвет effort: насыщенные, глубже чем пастельные (jewel tones) _effort_color() { case "$1" in low) printf '\033[38;5;220m[low]\033[00m' ;; # золотой - medium) printf '\033[38;5;43m[medium]\033[00m' ;; # бирюзовый - high) printf '\033[38;5;39m[high]\033[00m' ;; # небесно-голубой - xhigh) printf '\033[38;5;171m[xhigh]\033[00m' ;; # лавандовый - max) printf '\033[38;5;210m[\033[38;5;220mm\033[38;5;114ma\033[38;5;43mx\033[38;5;171m]\033[00m' ;; # радуга - *) printf '\033[38;5;250m[%s]\033[00m' "$1" ;; + medium) printf '\033[38;5;50m[medium]\033[00m' ;; # насыщенный teal + high) printf '\033[38;5;38m[high]\033[00m' ;; # глубокий голубой + xhigh) printf '\033[38;5;206m[xhigh]\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' ;; # радуга + *) printf '\033[38;5;252m[%s]\033[00m' "$1" ;; + esac +} + +# Брендовый цвет имени модели по лаунчеру +_brand_color() { + case "${1:-}" in + deepseek) printf '\033[38;5;69m' ;; # DeepSeek фирменный синий + claude) printf '\033[38;5;173m' ;; # Anthropic оранжевый + kimi) printf '\033[38;5;81m' ;; # Kimi голубой + openrouter) printf '\033[38;5;135m' ;; # OpenRouter фиолетовый + *) printf '\033[38;5;223m' ;; # кремовый (fallback) esac } branch=$(git -C "$cwd" --no-optional-locks symbolic-ref --short HEAD 2>/dev/null) short_cwd="${cwd/#$HOME/\~}" -printf "\033[38;5;250m%s\033[00m" "$short_cwd" +printf "\033[38;5;252m%s\033[00m" "$short_cwd" -[ -n "$branch" ] && printf " \033[38;5;250m[%s]\033[00m" "$branch" +[ -n "$branch" ] && printf " \033[38;5;252m[%s]\033[00m" "$branch" if [ -n "$model" ]; then + brand_color=$(_brand_color "${AI_LAUNCHER:-}") effort=$(echo "$input" | jq -r ".effort.level // empty") # Сохраняем effort для persistence между сессиями одного лаунчера - if [ -n "$effort" ] && [ -n "${AI_LAUNCHER:-}" ]; then + if [ -n "${AI_LAUNCHER:-}" ] && [ -n "$effort" ]; then effort_file="$HOME/.cache/ai-setup/effort_${AI_LAUNCHER}" prev_effort=$(cat "$effort_file" 2>/dev/null) if [ "$effort" != "$prev_effort" ]; then @@ -79,13 +91,13 @@ if [ -n "$model" ]; then fi fi fi - [ -n "$account" ] && printf " \033[38;5;223m[%s]\033[00m" "$account" + [ -n "$account" ] && printf " %s[%s]\033[00m" "$brand_color" "$account" fi if [ -n "$effort" ]; then - printf " \033[38;5;223m%s " "$model" + printf " %s%s " "$brand_color" "$model" _effort_color "$effort" else - printf " \033[38;5;223m%s\033[00m" "$model" + printf " %s%s\033[00m" "$brand_color" "$model" fi fi @@ -114,7 +126,7 @@ pct_color() { if [ "$pct" -lt 40 ]; then printf '\033[38;5;114m' # мягкий зелёный elif [ "$pct" -lt 60 ]; then - printf '\033[38;5;221m' # золотистый + printf '\033[38;5;220m' # золотой (как effort low) else printf '\033[38;5;210m' # мягкий красный fi @@ -127,7 +139,7 @@ if [[ "$model_id" == *deepseek* ]]; then cache_file="$HOME/.cache/ai-setup/deepseek_balance" if [ -f "$cache_file" ]; then balance=$(head -1 "$cache_file") - [ -n "$balance" ] && printf " \033[38;5;147m%s\033[00m" "$balance" + [ -n "$balance" ] && printf " \033[38;5;183m%s\033[00m" "$balance" fi # Фоновое обновление баланса (не чаще раза в 30 секунд) diff --git a/scripts/ai-setup.sh b/scripts/ai-setup.sh index 6f0e67c..398fd35 100755 --- a/scripts/ai-setup.sh +++ b/scripts/ai-setup.sh @@ -1106,6 +1106,44 @@ with open(settings_path, 'w') as f: PYEOF } +_restore_model() { + local default_model="${1:-}" + local launcher="${AI_LAUNCHER:-}" + [ -z "$launcher" ] && return + local model_file="$HOME/.cache/ai-setup/model_${launcher}" + local model + model=$(cat "$model_file" 2>/dev/null) + [ -z "$model" ] && model="$default_model" + [ -z "$model" ] && return + python3 - "$HOME/.claude/settings.json" "$model" <<'PYEOF' +import sys, json, os +settings_path, model = sys.argv[1], sys.argv[2] +data = {} +if os.path.exists(settings_path): + try: + with open(settings_path) as f: + data = json.load(f) + except Exception: + pass +data['model'] = model +with open(settings_path, 'w') as f: + json.dump(data, f, indent=2, ensure_ascii=False) + f.write('\n') +PYEOF +} + +# _restore_model_str: возвращает сохранённую модель строкой (для ANTHROPIC_MODEL env var) +_restore_model_str() { + local default_model="${1:-}" + local launcher="${AI_LAUNCHER:-}" + [ -z "$launcher" ] && echo "$default_model" && return + local model_file="$HOME/.cache/ai-setup/model_${launcher}" + local model + model=$(cat "$model_file" 2>/dev/null) + [ -z "$model" ] && model="$default_model" + echo "$model" +} + _build_ai_sys_prompt() { local global_rules="$HOME/.config/ai-setup/global_rules.md" local global_rendered="" @@ -1377,9 +1415,10 @@ trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM _build_ai_sys_prompt > "$_PROMPT_FILE" export AI_LAUNCHER=openrouter _restore_effort high +_MODEL=$(_restore_model_str "openai/gpt-5.5") ANTHROPIC_BASE_URL=https://openrouter.ai/api \ ANTHROPIC_AUTH_TOKEN="$api_key" \ -ANTHROPIC_MODEL=openai/gpt-5.5 \ +ANTHROPIC_MODEL=$_MODEL \ ANTHROPIC_DEFAULT_OPUS_MODEL=anthropic/claude-4.8-opus \ ANTHROPIC_DEFAULT_SONNET_MODEL=anthropic/claude-4.6-sonnet \ ANTHROPIC_DEFAULT_HAIKU_MODEL=openai/gpt-5.5 \ @@ -1431,7 +1470,8 @@ trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM _build_ai_sys_prompt > "$_PROMPT_FILE" export AI_LAUNCHER=claude _restore_effort xhigh -claude --dangerously-skip-permissions --model sonnet --system-prompt-file "$_PROMPT_FILE" "$@" +_restore_model "sonnet" +claude --dangerously-skip-permissions --system-prompt-file "$_PROMPT_FILE" "$@" CLAUDEEOF chmod +x "$BIN_DIR/ai-claude"