Compare commits
3 Commits
6c7324bfd8
...
775bca1cee
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
775bca1cee | ||
|
|
2079768318 | ||
|
|
cf34698116 |
@@ -3,7 +3,6 @@ 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')
|
||||||
session_id=$(echo "$input" | jq -r '.session_id // empty')
|
|
||||||
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')
|
||||||
@@ -18,69 +17,6 @@ printf "\033[00;37m%s\033[00m" "$short_cwd"
|
|||||||
[ -n "$branch" ] && printf " \033[00;37m[%s]\033[00m" "$branch"
|
[ -n "$branch" ] && printf " \033[00;37m[%s]\033[00m" "$branch"
|
||||||
[ -n "$model" ] && printf " \033[38;5;173m%s\033[00m" "$model"
|
[ -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() {
|
fmt_remaining() {
|
||||||
local reset_ts="$1"
|
local reset_ts="$1"
|
||||||
@@ -112,8 +48,72 @@ pct_color() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Рейт-лимиты для Anthropic / Kimi / прочих (НЕ DeepSeek)
|
# --- Баланс DeepSeek ---
|
||||||
if [[ "$model_id" != *deepseek* ]]; then
|
# Моментально показываем кэшированный баланс, в фоне обновляем через API.
|
||||||
|
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[00;35m\$%s\033[00m" "$balance"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Фоновое обновление баланса (не чаще раза в 30 секунд)
|
||||||
|
refresh_ts="$HOME/.cache/ai-setup/deepseek_balance_refresh_ts"
|
||||||
|
now=$(date +%s)
|
||||||
|
last=$(cat "$refresh_ts" 2>/dev/null || echo 0)
|
||||||
|
if [ $(( now - last )) -gt 30 ]; then
|
||||||
|
key_file="$HOME/.config/ai-setup/deepseek_key"
|
||||||
|
if [ -f "$key_file" ]; then
|
||||||
|
echo "$now" > "$refresh_ts" 2>/dev/null
|
||||||
|
(
|
||||||
|
api_key=$(cat "$key_file")
|
||||||
|
resp=$(curl -s --max-time 10 "https://api.deepseek.com/user/balance" \
|
||||||
|
-H "Authorization: Bearer $api_key" \
|
||||||
|
-H "Accept: application/json" 2>/dev/null)
|
||||||
|
if [ -n "$resp" ]; then
|
||||||
|
new_balance=$(echo "$resp" | python3 -c "
|
||||||
|
import sys, json
|
||||||
|
d = json.load(sys.stdin)
|
||||||
|
infos = d.get('balance_infos', [])
|
||||||
|
if infos:
|
||||||
|
curr = infos[0].get('currency', '')
|
||||||
|
total = infos[0].get('total_balance', '0')
|
||||||
|
print(f'{total} {curr}')
|
||||||
|
" 2>/dev/null)
|
||||||
|
if [ -n "$new_balance" ]; then
|
||||||
|
echo "$new_balance" > "$cache_file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
) &
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Рейт-лимиты для НЕ-DeepSeek провайдеров
|
||||||
|
# Кеш специфичен для провайдера (по model_id) чтобы не смешивать claude/kimi/openrouter
|
||||||
|
_cache_key=$(echo "${model_id:-unknown}" | sed 's/[^a-zA-Z0-9._-]/_/g')
|
||||||
|
RATE_CACHE="$HOME/.cache/ai-setup/rate_limits_${_cache_key}.cache"
|
||||||
|
mkdir -p "$HOME/.cache/ai-setup"
|
||||||
|
|
||||||
|
# Если есть свежие данные - сохранить в кеш
|
||||||
|
if [ -n "$five_pct" ] || [ -n "$week_pct" ]; then
|
||||||
|
{
|
||||||
|
echo "FIVE_PCT=${five_pct}"
|
||||||
|
echo "FIVE_RESET=${five_reset}"
|
||||||
|
echo "WEEK_PCT=${week_pct}"
|
||||||
|
echo "WEEK_RESET=${week_reset}"
|
||||||
|
} > "$RATE_CACHE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Если нет данных - читать из кеша (старт сессии до первого запроса)
|
||||||
|
if [ -z "$five_pct" ] && [ -z "$week_pct" ] && [ -f "$RATE_CACHE" ]; then
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$RATE_CACHE" 2>/dev/null
|
||||||
|
five_pct="${FIVE_PCT:-}"
|
||||||
|
five_reset="${FIVE_RESET:-}"
|
||||||
|
week_pct="${WEEK_PCT:-}"
|
||||||
|
week_reset="${WEEK_RESET:-}"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$five_pct" ] && [ -n "$five_reset" ]; then
|
if [ -n "$five_pct" ] && [ -n "$five_reset" ]; then
|
||||||
five_int=$(printf '%.0f' "$five_pct")
|
five_int=$(printf '%.0f' "$five_pct")
|
||||||
remaining=$(fmt_remaining "$five_reset")
|
remaining=$(fmt_remaining "$five_reset")
|
||||||
@@ -128,6 +128,9 @@ if [[ "$model_id" != *deepseek* ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ctx:0% при старте новой сессии (нет данных от API)
|
||||||
|
[ -z "$ctx_pct" ] && ctx_pct="0"
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
@@ -658,6 +658,11 @@ if os.path.exists(settings_path):
|
|||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
pass
|
pass
|
||||||
data["statusLine"] = {"type": "command", "command": f"bash {script_path}"}
|
data["statusLine"] = {"type": "command", "command": f"bash {script_path}"}
|
||||||
|
# SessionStart хук - триггерит вызов statusLine при старте сессии
|
||||||
|
if "hooks" not in data:
|
||||||
|
data["hooks"] = {}
|
||||||
|
if "SessionStart" not in data["hooks"]:
|
||||||
|
data["hooks"]["SessionStart"] = [{"hooks": [{"type": "command", "command": "true"}]}]
|
||||||
with open(settings_path, "w") as f:
|
with open(settings_path, "w") as f:
|
||||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
@@ -1107,7 +1112,9 @@ if [ -z "$api_key" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SYS_PROMPT=$(_build_ai_sys_prompt)
|
_PROMPT_FILE=$(mktemp /tmp/ai-sys-prompt.XXXXXX)
|
||||||
|
trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM
|
||||||
|
_build_ai_sys_prompt > "$_PROMPT_FILE"
|
||||||
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic \
|
ANTHROPIC_BASE_URL=https://api.deepseek.com/anthropic \
|
||||||
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
||||||
ANTHROPIC_MODEL=deepseek-v4-pro \
|
ANTHROPIC_MODEL=deepseek-v4-pro \
|
||||||
@@ -1116,7 +1123,7 @@ ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-v4-pro \
|
|||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-v4-flash \
|
ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-v4-flash \
|
||||||
CLAUDE_CODE_SUBAGENT_MODEL=deepseek-v4-flash \
|
CLAUDE_CODE_SUBAGENT_MODEL=deepseek-v4-flash \
|
||||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
||||||
claude --dangerously-skip-permissions --system-prompt "$SYS_PROMPT" "$@"
|
claude --dangerously-skip-permissions --system-prompt-file "$_PROMPT_FILE" "$@"
|
||||||
DEEPSEEKEOF
|
DEEPSEEKEOF
|
||||||
chmod +x "$BIN_DIR/ai-deepseek"
|
chmod +x "$BIN_DIR/ai-deepseek"
|
||||||
|
|
||||||
@@ -1177,7 +1184,9 @@ if ! command -v claude &>/dev/null; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SYS_PROMPT=$(_build_ai_sys_prompt)
|
_PROMPT_FILE=$(mktemp /tmp/ai-sys-prompt.XXXXXX)
|
||||||
|
trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM
|
||||||
|
_build_ai_sys_prompt > "$_PROMPT_FILE"
|
||||||
ANTHROPIC_BASE_URL=https://api.kimi.com/coding \
|
ANTHROPIC_BASE_URL=https://api.kimi.com/coding \
|
||||||
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
||||||
ANTHROPIC_MODEL=kimi-k2.6 \
|
ANTHROPIC_MODEL=kimi-k2.6 \
|
||||||
@@ -1186,7 +1195,7 @@ ANTHROPIC_DEFAULT_SONNET_MODEL=kimi-k2.6 \
|
|||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL=kimi-k2.6 \
|
ANTHROPIC_DEFAULT_HAIKU_MODEL=kimi-k2.6 \
|
||||||
CLAUDE_CODE_SUBAGENT_MODEL=kimi-k2.6 \
|
CLAUDE_CODE_SUBAGENT_MODEL=kimi-k2.6 \
|
||||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
||||||
claude --dangerously-skip-permissions --system-prompt "$SYS_PROMPT" "$@"
|
claude --dangerously-skip-permissions --system-prompt-file "$_PROMPT_FILE" "$@"
|
||||||
KIMIEOF
|
KIMIEOF
|
||||||
chmod +x "$BIN_DIR/ai-kimi"
|
chmod +x "$BIN_DIR/ai-kimi"
|
||||||
|
|
||||||
@@ -1247,7 +1256,9 @@ if ! command -v claude &>/dev/null; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SYS_PROMPT=$(_build_ai_sys_prompt)
|
_PROMPT_FILE=$(mktemp /tmp/ai-sys-prompt.XXXXXX)
|
||||||
|
trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM
|
||||||
|
_build_ai_sys_prompt > "$_PROMPT_FILE"
|
||||||
ANTHROPIC_BASE_URL=https://openrouter.ai/api \
|
ANTHROPIC_BASE_URL=https://openrouter.ai/api \
|
||||||
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
ANTHROPIC_AUTH_TOKEN="$api_key" \
|
||||||
ANTHROPIC_MODEL=openai/gpt-5.5 \
|
ANTHROPIC_MODEL=openai/gpt-5.5 \
|
||||||
@@ -1256,7 +1267,7 @@ ANTHROPIC_DEFAULT_SONNET_MODEL=anthropic/claude-4.6-sonnet \
|
|||||||
ANTHROPIC_DEFAULT_HAIKU_MODEL=openai/gpt-5.5 \
|
ANTHROPIC_DEFAULT_HAIKU_MODEL=openai/gpt-5.5 \
|
||||||
CLAUDE_CODE_SUBAGENT_MODEL=openai/gpt-5.5 \
|
CLAUDE_CODE_SUBAGENT_MODEL=openai/gpt-5.5 \
|
||||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
||||||
claude --dangerously-skip-permissions --system-prompt "$SYS_PROMPT" "$@"
|
claude --dangerously-skip-permissions --system-prompt-file "$_PROMPT_FILE" "$@"
|
||||||
OPENROUTEREOF
|
OPENROUTEREOF
|
||||||
chmod +x "$BIN_DIR/ai-openrouter"
|
chmod +x "$BIN_DIR/ai-openrouter"
|
||||||
|
|
||||||
@@ -1295,8 +1306,10 @@ cat > "$BIN_DIR/ai-claude" << 'CLAUDEEOF'
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# ai-claude - запуск оригинального Claude Code (Anthropic)
|
# ai-claude - запуск оригинального Claude Code (Anthropic)
|
||||||
source "$HOME/.local/bin/ai-api-helpers.sh" 2>/dev/null || true
|
source "$HOME/.local/bin/ai-api-helpers.sh" 2>/dev/null || true
|
||||||
SYS_PROMPT=$(_build_ai_sys_prompt)
|
_PROMPT_FILE=$(mktemp /tmp/ai-sys-prompt.XXXXXX)
|
||||||
exec claude --dangerously-skip-permissions --system-prompt "$SYS_PROMPT" "$@"
|
trap 'rm -f "$_PROMPT_FILE"' EXIT INT TERM
|
||||||
|
_build_ai_sys_prompt > "$_PROMPT_FILE"
|
||||||
|
claude --dangerously-skip-permissions --model sonnet --system-prompt-file "$_PROMPT_FILE" "$@"
|
||||||
CLAUDEEOF
|
CLAUDEEOF
|
||||||
chmod +x "$BIN_DIR/ai-claude"
|
chmod +x "$BIN_DIR/ai-claude"
|
||||||
|
|
||||||
@@ -1308,7 +1321,7 @@ if [ "$USE_VLESS" -eq 1 ]; then
|
|||||||
sed -i 's/^claude --dangerously-skip-permissions/proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" claude --dangerously-skip-permissions/' "$BIN_DIR/ai-kimi"
|
sed -i 's/^claude --dangerously-skip-permissions/proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" claude --dangerously-skip-permissions/' "$BIN_DIR/ai-kimi"
|
||||||
sed -i 's/^claude --dangerously-skip-permissions/proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" claude --dangerously-skip-permissions/' "$BIN_DIR/ai-openrouter"
|
sed -i 's/^claude --dangerously-skip-permissions/proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" claude --dangerously-skip-permissions/' "$BIN_DIR/ai-openrouter"
|
||||||
sed -i 's/^\([[:space:]]*\)exec "\$agy_bin"/\1exec proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" "\$agy_bin"/' "$BIN_DIR/ai-gemini"
|
sed -i 's/^\([[:space:]]*\)exec "\$agy_bin"/\1exec proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" "\$agy_bin"/' "$BIN_DIR/ai-gemini"
|
||||||
sed -i 's/^exec claude/exec proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" claude/' "$BIN_DIR/ai-claude"
|
sed -i 's/^claude --dangerously-skip-permissions/proxychains4 -f "\$HOME\/\.proxychains-xray\.conf" claude --dangerously-skip-permissions/' "$BIN_DIR/ai-claude"
|
||||||
success "proxychains4 интегрирован"
|
success "proxychains4 интегрирован"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
2
setup.sh
2
setup.sh
@@ -100,7 +100,7 @@ case "$choice" in
|
|||||||
saved_dev=$(grep '^DEV=' "$net_conf" | cut -d= -f2)
|
saved_dev=$(grep '^DEV=' "$net_conf" | cut -d= -f2)
|
||||||
saved_local_dns=$(grep '^LOCAL_DNS=' "$net_conf" | cut -d= -f2)
|
saved_local_dns=$(grep '^LOCAL_DNS=' "$net_conf" | cut -d= -f2)
|
||||||
saved_amn_srv=$(grep '^AMNEZIA_SERVER=' "$net_conf" | cut -d= -f2)
|
saved_amn_srv=$(grep '^AMNEZIA_SERVER=' "$net_conf" | cut -d= -f2)
|
||||||
saved_ks_exc=$(grep '^KS_EXCEPTIONS=' "$net_conf" | cut -d= -f2)
|
saved_ks_exc=$(grep '^KILL_SWITCH_EXCEPTIONS=' "$net_conf" | cut -d= -f2)
|
||||||
auto_gw="${saved_gw:-$auto_gw}"
|
auto_gw="${saved_gw:-$auto_gw}"
|
||||||
auto_dev="${saved_dev:-$auto_dev}"
|
auto_dev="${saved_dev:-$auto_dev}"
|
||||||
echo -e "Загружены параметры профиля ${BLD}${chosen_profile}${CLR}: GATEWAY=${BLD}${auto_gw}${CLR} DEV=${BLD}${auto_dev}${CLR}"
|
echo -e "Загружены параметры профиля ${BLD}${chosen_profile}${CLR}: GATEWAY=${BLD}${auto_gw}${CLR} DEV=${BLD}${auto_dev}${CLR}"
|
||||||
|
|||||||
Reference in New Issue
Block a user