Fix proxy handling and improve error reporting
- Add wrapper proxy for fixing effort level in claude-code-proxy - Improve proxy cleanup trap to include wrapper - Add credential backup and restore for ChatGPT to prevent Anthropic keys deletion on /logout - Enhance error messages for 400 and other HTTP errors in ChatGPT and Gemini handlers
This commit is contained in:
163
claude_setup.sh
163
claude_setup.sh
@@ -106,6 +106,60 @@ else
|
|||||||
install_proxy
|
install_proxy
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# ── 4b. effort-proxy wrapper (патч xhigh→max для claude-code-proxy) ─────────
|
||||||
|
EFFORT_PROXY_BIN="$HOME/.local/bin/claude-gpt-effort-proxy.py"
|
||||||
|
cat > "$EFFORT_PROXY_BIN" << 'PYEOF'
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Reverse proxy: rewrites "xhigh" effort → "max" for claude-code-proxy (bug in ≤0.0.13)."""
|
||||||
|
import http.client, http.server, sys
|
||||||
|
|
||||||
|
UPSTREAM_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 18766
|
||||||
|
LISTEN_PORT = int(sys.argv[2]) if len(sys.argv) > 2 else 18765
|
||||||
|
|
||||||
|
class _Proxy(http.server.BaseHTTPRequestHandler):
|
||||||
|
def proxy_request(self):
|
||||||
|
body = b""
|
||||||
|
if cl := self.headers.get("Content-Length"):
|
||||||
|
body = self.rfile.read(int(cl))
|
||||||
|
body = body.replace(b'"xhigh"', b'"max"')
|
||||||
|
try:
|
||||||
|
conn = http.client.HTTPConnection("localhost", UPSTREAM_PORT, timeout=300)
|
||||||
|
hdrs = dict(self.headers)
|
||||||
|
hdrs.pop("Host", None)
|
||||||
|
hdrs["Content-Length"] = str(len(body))
|
||||||
|
conn.request(self.command, self.path, body=body or None, headers=hdrs)
|
||||||
|
resp = conn.getresponse()
|
||||||
|
self.send_response(resp.status, resp.reason)
|
||||||
|
chunked = False
|
||||||
|
for k, v in resp.getheaders():
|
||||||
|
if k.lower() == "transfer-encoding" and "chunked" in v.lower():
|
||||||
|
chunked = True
|
||||||
|
self.send_header(k, v)
|
||||||
|
self.end_headers()
|
||||||
|
while chunk := resp.read(4096):
|
||||||
|
try:
|
||||||
|
if chunked:
|
||||||
|
self.wfile.write(f"{len(chunk):X}\r\n".encode() + chunk + b"\r\n")
|
||||||
|
else:
|
||||||
|
self.wfile.write(chunk)
|
||||||
|
self.wfile.flush()
|
||||||
|
except (BrokenPipeError, ConnectionResetError):
|
||||||
|
break
|
||||||
|
if chunked:
|
||||||
|
try: self.wfile.write(b"0\r\n\r\n")
|
||||||
|
except: pass
|
||||||
|
conn.close()
|
||||||
|
except Exception as e:
|
||||||
|
try: self.send_error(502, str(e))
|
||||||
|
except: pass
|
||||||
|
do_GET = do_POST = do_PUT = do_DELETE = do_HEAD = proxy_request
|
||||||
|
def log_message(self, *args): pass
|
||||||
|
|
||||||
|
http.server.HTTPServer(("localhost", LISTEN_PORT), _Proxy).serve_forever()
|
||||||
|
PYEOF
|
||||||
|
chmod +x "$EFFORT_PROXY_BIN"
|
||||||
|
success "claude-gpt-effort-proxy -> $EFFORT_PROXY_BIN"
|
||||||
|
|
||||||
# ── 5. antigravity-claude-proxy (Gemini) ────────────────────
|
# ── 5. antigravity-claude-proxy (Gemini) ────────────────────
|
||||||
info "Проверяю antigravity-claude-proxy..."
|
info "Проверяю antigravity-claude-proxy..."
|
||||||
if command -v antigravity-claude-proxy &>/dev/null || command -v acc &>/dev/null; then
|
if command -v antigravity-claude-proxy &>/dev/null || command -v acc &>/dev/null; then
|
||||||
@@ -375,20 +429,44 @@ claude_gpt() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Запускаем прокси в фоне (если ещё не запущен)
|
# Запускаем прокси в фоне (если ещё не запущен)
|
||||||
local proxy_pid=""
|
local proxy_pid="" wrapper_pid=""
|
||||||
|
local effort_proxy="$HOME/.local/bin/claude-gpt-effort-proxy.py"
|
||||||
|
|
||||||
|
# Если прокси занял порт 18765 (старый формат без wrapper) — мигрируем
|
||||||
|
if pgrep -f "claude-code-proxy serve" &>/dev/null && \
|
||||||
|
! pgrep -f "claude-gpt-effort-proxy" &>/dev/null; then
|
||||||
|
pkill -f "claude-code-proxy serve" 2>/dev/null
|
||||||
|
sleep 0.5
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Реальный прокси на 18766
|
||||||
if ! pgrep -f "claude-code-proxy serve" &>/dev/null; then
|
if ! pgrep -f "claude-code-proxy serve" &>/dev/null; then
|
||||||
"$proxy_bin" serve &>/tmp/claude-code-proxy.log &
|
PORT=18766 "$proxy_bin" serve &>/tmp/claude-code-proxy.log &
|
||||||
proxy_pid=$!
|
proxy_pid=$!
|
||||||
|
local _j=0
|
||||||
|
while [ $_j -lt 10 ]; do
|
||||||
|
sleep 1
|
||||||
|
curl -sf --max-time 1 http://localhost:18766/ &>/dev/null
|
||||||
|
[ "$?" -ne 7 ] && break
|
||||||
|
_j=$((_j + 1))
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wrapper (xhigh→max патч) на 18765
|
||||||
|
if ! pgrep -f "claude-gpt-effort-proxy" &>/dev/null; then
|
||||||
|
python3 "$effort_proxy" 18766 18765 &>/tmp/claude-gpt-effort-proxy.log &
|
||||||
|
wrapper_pid=$!
|
||||||
local _i=0
|
local _i=0
|
||||||
while [ $_i -lt 10 ]; do
|
while [ $_i -lt 10 ]; do
|
||||||
sleep 1
|
sleep 1
|
||||||
curl -sf --max-time 1 http://localhost:18765/ &>/dev/null; local _ce=$?
|
curl -sf --max-time 1 http://localhost:18765/ &>/dev/null; local _ce=$?
|
||||||
[ "$_ce" -ne 7 ] && break # exit 7 = connection refused; любой другой = прокси слушает
|
[ "$_ce" -ne 7 ] && break # exit 7 = connection refused; любой другой = wrapper слушает
|
||||||
_i=$((_i + 1))
|
_i=$((_i + 1))
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
# Убиваем прокси при любом выходе из функции (early return или нормальный)
|
|
||||||
trap '[ -n "$proxy_pid" ] && kill "$proxy_pid" 2>/dev/null' RETURN
|
# Убиваем прокси и wrapper при любом выходе из функции
|
||||||
|
trap '[ -n "$proxy_pid" ] && kill "$proxy_pid" 2>/dev/null; [ -n "$wrapper_pid" ] && kill "$wrapper_pid" 2>/dev/null' RETURN
|
||||||
|
|
||||||
# ── Pre-launch API validation through proxy ──
|
# ── Pre-launch API validation through proxy ──
|
||||||
echo -n "Проверка авторизации ChatGPT... "
|
echo -n "Проверка авторизации ChatGPT... "
|
||||||
@@ -417,7 +495,7 @@ claude_gpt() {
|
|||||||
fi
|
fi
|
||||||
echo -n "Проверяю авторизацию после входа... "
|
echo -n "Проверяю авторизацию после входа... "
|
||||||
_claude_test_api "http://localhost:18765/v1/messages" "x-api-key: dummy" "gpt-5.4-mini"
|
_claude_test_api "http://localhost:18765/v1/messages" "x-api-key: dummy" "gpt-5.4-mini"
|
||||||
if [ "$_CLAUDE_TEST_CODE" != "200" ]; then
|
if [ "$_CLAUDE_TEST_CODE" != "200" ] && [ "$_CLAUDE_TEST_CODE" != "400" ]; then
|
||||||
echo -e "\033[0;31mОШИБКА (HTTP $_CLAUDE_TEST_CODE)\033[0m"
|
echo -e "\033[0;31mОШИБКА (HTTP $_CLAUDE_TEST_CODE)\033[0m"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -433,6 +511,11 @@ claude_gpt() {
|
|||||||
[ -n "$_emsg" ] && echo " $_emsg"
|
[ -n "$_emsg" ] && echo " $_emsg"
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
|
400)
|
||||||
|
# Прокси работает — 400 означает только, что тест-запрос не содержит обязательное поле «instructions»
|
||||||
|
# Авторизация уже проверена через codex auth status; запускаем Claude
|
||||||
|
echo -e "\033[0;32mOK\033[0m"
|
||||||
|
;;
|
||||||
000)
|
000)
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\033[0;33m[СЕТЬ]\033[0m Не удалось проверить ChatGPT прокси (нет сети?). Продолжаю..."
|
echo -e "\033[0;33m[СЕТЬ]\033[0m Не удалось проверить ChatGPT прокси (нет сети?). Продолжаю..."
|
||||||
@@ -440,12 +523,26 @@ claude_gpt() {
|
|||||||
*)
|
*)
|
||||||
_emsg=$(_claude_extract_error "$_CLAUDE_TEST_BODY")
|
_emsg=$(_claude_extract_error "$_CLAUDE_TEST_BODY")
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\033[0;31m[ОШИБКА]\033[0m Прокси вернул HTTP $_CLAUDE_TEST_CODE"
|
echo -e "\033[0;31m[ОШИБКА]\033[0m Прокси вернул неожиданный HTTP $_CLAUDE_TEST_CODE."
|
||||||
[ -n "$_emsg" ] && echo " $_emsg"
|
[ -n "$_emsg" ] && echo " $_emsg"
|
||||||
|
echo ""
|
||||||
|
echo "Попробуйте:"
|
||||||
|
echo " • Перезапустить claude_gpt"
|
||||||
|
echo " • Переавторизоваться: claude-code-proxy codex auth logout && claude-code-proxy codex auth login"
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
# Сохраняем Anthropic credentials перед запуском — команда /logout внутри Claude Code
|
||||||
|
# удаляет их, хотя в режиме GPT они не нужны, но потом сломают claude_anthropic
|
||||||
|
local _creds_file="$HOME/.claude/.credentials.json"
|
||||||
|
local _creds_backup=""
|
||||||
|
[ -f "$_creds_file" ] && _creds_backup=$(cat "$_creds_file")
|
||||||
|
|
||||||
|
echo -e "\033[0;33m[ИНФО]\033[0m Режим ChatGPT. Для выхода: Ctrl+C или /exit"
|
||||||
|
echo -e " Команда \033[1m/logout\033[0m выйдет из Anthropic, а не из ChatGPT."
|
||||||
|
echo ""
|
||||||
|
|
||||||
ANTHROPIC_BASE_URL=http://localhost:18765 \
|
ANTHROPIC_BASE_URL=http://localhost:18765 \
|
||||||
ANTHROPIC_AUTH_TOKEN=dummy \
|
ANTHROPIC_AUTH_TOKEN=dummy \
|
||||||
ANTHROPIC_MODEL=gpt-5.5 \
|
ANTHROPIC_MODEL=gpt-5.5 \
|
||||||
@@ -456,6 +553,14 @@ claude_gpt() {
|
|||||||
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 \
|
||||||
claude "$@"
|
claude "$@"
|
||||||
|
|
||||||
|
# Восстанавливаем credentials если /logout их удалил
|
||||||
|
if [ -n "$_creds_backup" ] && [ ! -f "$_creds_file" ]; then
|
||||||
|
mkdir -p "$(dirname "$_creds_file")"
|
||||||
|
echo "$_creds_backup" > "$_creds_file"
|
||||||
|
echo ""
|
||||||
|
echo -e "\033[0;33m[ИНФО]\033[0m Anthropic credentials восстановлены после /logout внутри сессии."
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -n "$proxy_pid" ]; then
|
if [ -n "$proxy_pid" ]; then
|
||||||
kill "$proxy_pid" 2>/dev/null
|
kill "$proxy_pid" 2>/dev/null
|
||||||
wait "$proxy_pid" 2>/dev/null
|
wait "$proxy_pid" 2>/dev/null
|
||||||
@@ -841,6 +946,44 @@ except:
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
400)
|
||||||
|
_emsg=$(_claude_extract_error "$_CLAUDE_TEST_BODY")
|
||||||
|
echo ""
|
||||||
|
if echo "$_emsg" | grep -q "RESOURCE_EXHAUSTED"; then
|
||||||
|
local _reset
|
||||||
|
_reset=$(echo "$_emsg" | sed -n 's/.*reset after \([^.]*\).*/\1/p' 2>/dev/null || true)
|
||||||
|
echo -e "\033[0;33m[КВОТА ИСЧЕРПАНА]\033[0m Все Gemini аккаунты исчерпали лимит запросов."
|
||||||
|
[ -n "$_reset" ] && echo " Квота обновится через: $_reset"
|
||||||
|
echo ""
|
||||||
|
echo "Что делать:"
|
||||||
|
echo " • Подождите сброса квоты и повторите попытку"
|
||||||
|
echo " • Или добавьте новый аккаунт Google через http://localhost:8080"
|
||||||
|
if _claude_offer_reauth "Gemini (добавить аккаунт)"; then
|
||||||
|
xdg-open "http://localhost:8080" 2>/dev/null || \
|
||||||
|
sensible-browser "http://localhost:8080" 2>/dev/null || \
|
||||||
|
echo "Откройте http://localhost:8080"
|
||||||
|
echo "Нажмите Enter после добавления..."
|
||||||
|
read -r
|
||||||
|
echo -n "Проверяю авторизацию Gemini... "
|
||||||
|
_claude_test_api "http://localhost:8080/v1/messages" "x-api-key: dummy" "gemini-3-flash-agent"
|
||||||
|
if [ "$_CLAUDE_TEST_CODE" != "200" ]; then
|
||||||
|
echo -e "\033[0;31mОШИБКА (HTTP $_CLAUDE_TEST_CODE)\033[0m"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
echo -e "\033[0;32mOK\033[0m"
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "\033[0;31m[ОШИБКА]\033[0m Прокси Gemini вернул HTTP 400."
|
||||||
|
[ -n "$_emsg" ] && echo " $_emsg"
|
||||||
|
echo ""
|
||||||
|
echo "Попробуйте:"
|
||||||
|
echo " • Перезапустить прокси: перезапустите claude_gemini"
|
||||||
|
echo " • Проверить статус аккаунтов: http://localhost:8080"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
000)
|
000)
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\033[0;33m[СЕТЬ]\033[0m Не удалось проверить Gemini прокси (нет сети?). Продолжаю..."
|
echo -e "\033[0;33m[СЕТЬ]\033[0m Не удалось проверить Gemini прокси (нет сети?). Продолжаю..."
|
||||||
@@ -848,8 +991,12 @@ except:
|
|||||||
*)
|
*)
|
||||||
_emsg=$(_claude_extract_error "$_CLAUDE_TEST_BODY")
|
_emsg=$(_claude_extract_error "$_CLAUDE_TEST_BODY")
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\033[0;31m[ОШИБКА]\033[0m Прокси вернул HTTP $_CLAUDE_TEST_CODE"
|
echo -e "\033[0;31m[ОШИБКА]\033[0m Прокси вернул неожиданный HTTP $_CLAUDE_TEST_CODE."
|
||||||
[ -n "$_emsg" ] && echo " $_emsg"
|
[ -n "$_emsg" ] && echo " $_emsg"
|
||||||
|
echo ""
|
||||||
|
echo "Попробуйте:"
|
||||||
|
echo " • Перезапустить claude_gemini"
|
||||||
|
echo " • Проверить статус аккаунтов: http://localhost:8080"
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
Reference in New Issue
Block a user