DeepSeek: накопленная стоимость сессии по DeepSeek-ценам (V4: $0.55/$2.19, V3: $0.27/$1.10) Anthropic/Kimi/прочие: рейт-лимиты (5h, 7d) без долларов Все: заполнение контекста (ctx%) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
149 lines
5.2 KiB
Bash
149 lines
5.2 KiB
Bash
#!/bin/bash
|
||
input=$(cat)
|
||
cwd=$(echo "$input" | jq -r '.cwd')
|
||
model=$(echo "$input" | jq -r '.model.display_name // empty')
|
||
model_id=$(echo "$input" | jq -r '.model.id // empty')
|
||
session_id=$(echo "$input" | jq -r '.session_id // 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')
|
||
week_pct=$(echo "$input" | jq -r '.rate_limits.seven_day.used_percentage // empty')
|
||
week_reset=$(echo "$input" | jq -r '.rate_limits.seven_day.resets_at // empty')
|
||
ctx_pct=$(echo "$input" | jq -r '.context_window.used_percentage // empty')
|
||
|
||
branch=$(git -C "$cwd" --no-optional-locks symbolic-ref --short HEAD 2>/dev/null)
|
||
|
||
short_cwd="${cwd/#$HOME/\~}"
|
||
printf "\033[00;37m%s\033[00m" "$short_cwd"
|
||
|
||
[ -n "$branch" ] && printf " \033[00;37m[%s]\033[00m" "$branch"
|
||
[ -n "$model" ] && printf " \033[38;5;173m%s\033[00m" "$model"
|
||
|
||
# --- Накопленная стоимость DeepSeek (per-request) ---
|
||
|
||
COST_FILE="$HOME/.cache/ai-setup/deepseek_cost_state"
|
||
|
||
if [[ "$model_id" == *deepseek* ]] && [ -n "$session_id" ]; then
|
||
# Цены DeepSeek за 1M токенов
|
||
case "$model_id" in
|
||
*deepseek-v4*|*deepseek-reasoner*)
|
||
inp_p=0.55; out_p=2.19; cc_p=0.55; cr_p=0.14 ;;
|
||
*deepseek-chat*|*deepseek-v3*|*deepseek*)
|
||
inp_p=0.27; out_p=1.10; cc_p=0.27; cr_p=0.07 ;;
|
||
*)
|
||
inp_p=0.27; out_p=1.10; cc_p=0.27; cr_p=0.07 ;;
|
||
esac
|
||
|
||
usage=$(echo "$input" | jq -r '.context_window.current_usage // empty')
|
||
|
||
if [ -n "$usage" ] && [ "$usage" != "null" ]; then
|
||
in_tok=$(echo "$usage" | jq -r '.input_tokens // 0')
|
||
out_tok=$(echo "$usage" | jq -r '.output_tokens // 0')
|
||
cc_tok=$(echo "$usage" | jq -r '.cache_creation_input_tokens // 0')
|
||
cr_tok=$(echo "$usage" | jq -r '.cache_read_input_tokens // 0')
|
||
|
||
last_cost=$(echo "scale=10; ($in_tok * $inp_p + $out_tok * $out_p + $cc_tok * $cc_p + $cr_tok * $cr_p) / 1000000" | bc -l)
|
||
|
||
# Читаем накопленное
|
||
if [ -f "$COST_FILE" ]; then
|
||
existing=$(grep "^${session_id}|" "$COST_FILE" 2>/dev/null | tail -1)
|
||
fi
|
||
|
||
if [ -n "$existing" ]; then
|
||
IFS='|' read -r sid old_in old_out old_cc old_cr old_total <<< "$existing"
|
||
if [ "$old_in" = "$in_tok" ] && [ "$old_out" = "$out_tok" ] && [ "$old_cc" = "$cc_tok" ] && [ "$old_cr" = "$cr_tok" ]; then
|
||
accumulated="$old_total"
|
||
else
|
||
accumulated=$(echo "scale=6; $old_total + $last_cost" | bc -l)
|
||
fi
|
||
else
|
||
accumulated="$last_cost"
|
||
fi
|
||
|
||
mkdir -p "$(dirname "$COST_FILE")"
|
||
grep -v "^${session_id}|" "$COST_FILE" 2>/dev/null > "$COST_FILE.tmp" || true
|
||
echo "${session_id}|${in_tok}|${out_tok}|${cc_tok}|${cr_tok}|${accumulated}" >> "$COST_FILE.tmp"
|
||
mv "$COST_FILE.tmp" "$COST_FILE" 2>/dev/null
|
||
|
||
deepseek_cost="$accumulated"
|
||
else
|
||
if [ -f "$COST_FILE" ]; then
|
||
existing=$(grep "^${session_id}|" "$COST_FILE" 2>/dev/null | tail -1)
|
||
if [ -n "$existing" ]; then
|
||
IFS='|' read -r sid _ _ _ _ total <<< "$existing"
|
||
deepseek_cost="$total"
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
cost_int=$(printf '%.0f' "$deepseek_cost" 2>/dev/null)
|
||
if [ "$cost_int" -gt 0 ] 2>/dev/null; then
|
||
printf " \033[00;35m\$%.2f\033[00m" "$deepseek_cost"
|
||
fi
|
||
fi
|
||
|
||
# Форматирует оставшееся время до сброса лимита
|
||
fmt_remaining() {
|
||
local reset_ts="$1"
|
||
local now
|
||
now=$(date +%s)
|
||
local diff=$(( reset_ts - now ))
|
||
[ "$diff" -le 0 ] && echo "скоро" && return
|
||
local d=$(( diff / 86400 ))
|
||
local h=$(( (diff % 86400) / 3600 ))
|
||
local m=$(( (diff % 3600) / 60 ))
|
||
if [ "$d" -gt 0 ]; then
|
||
echo "${d}д${h}ч"
|
||
elif [ "$h" -gt 0 ]; then
|
||
echo "${h}ч${m}м"
|
||
else
|
||
echo "${m}м"
|
||
fi
|
||
}
|
||
|
||
# Возвращает ANSI-цвет по проценту: зелёный <40%, жёлтый 40-60%, красный >=60%
|
||
pct_color() {
|
||
local pct="$1"
|
||
if [ "$pct" -lt 40 ]; then
|
||
printf '\033[00;32m'
|
||
elif [ "$pct" -lt 60 ]; then
|
||
printf '\033[00;33m'
|
||
else
|
||
printf '\033[00;31m'
|
||
fi
|
||
}
|
||
|
||
# Рейт-лимиты для Anthropic / Kimi / прочих (НЕ DeepSeek)
|
||
if [[ "$model_id" != *deepseek* ]]; then
|
||
if [ -n "$five_pct" ] && [ -n "$five_reset" ]; then
|
||
five_int=$(printf '%.0f' "$five_pct")
|
||
remaining=$(fmt_remaining "$five_reset")
|
||
color=$(pct_color "$five_int")
|
||
printf " %s%s:%s%%\033[00m" "$color" "$remaining" "$five_int"
|
||
fi
|
||
if [ -n "$week_pct" ] && [ -n "$week_reset" ]; then
|
||
week_int=$(printf '%.0f' "$week_pct")
|
||
remaining=$(fmt_remaining "$week_reset")
|
||
color=$(pct_color "$week_int")
|
||
printf " %s%s:%s%%\033[00m" "$color" "$remaining" "$week_int"
|
||
fi
|
||
fi
|
||
|
||
if [ -n "$ctx_pct" ]; then
|
||
ctx_int=$(printf '%.0f' "$ctx_pct")
|
||
color=$(pct_color "$ctx_int")
|
||
printf " %sctx:%s%%\033[00m" "$color" "$ctx_int"
|
||
|
||
# Звуковой сигнал при первом достижении 60%
|
||
alert_file="$HOME/.cache/ai-setup/ctx_alert_state"
|
||
if [ "$ctx_int" -ge 60 ]; then
|
||
if [ ! -f "$alert_file" ] || [ "$(cat "$alert_file")" != "alerted" ]; then
|
||
mkdir -p "$HOME/.cache/ai-setup"
|
||
echo "alerted" > "$alert_file"
|
||
(timeout 1s paplay /usr/share/sounds/freedesktop/stereo/alarm-clock-elapsed.oga 2>/dev/null; true) &
|
||
fi
|
||
elif [ "$ctx_int" -lt 50 ]; then
|
||
rm -f "$alert_file" 2>/dev/null
|
||
fi
|
||
fi
|
||
exit 0
|