From beea20686befa05d37263635f81f837dfac3551c Mon Sep 17 00:00:00 2001 From: admin Date: Fri, 22 May 2026 13:14:51 +0400 Subject: [PATCH] =?UTF-8?q?v3.6.0=20=E2=80=94=20Performance=20&=20Stabilit?= =?UTF-8?q?y=20Hardening?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P0: Connection pooling (http.client reuse per host), stream idle timeout (300s via selectors) on all streaming paths (OA/CC/Gemini/auto-continue) P1: Retry-After header support on all retry paths, preemptive OAuth token refresh (5min before expiry) P2: oa_convert_tools(strict=) for Responses vs Chat Completions, filter null/empty tool names P3: Response store TTL (600s eviction), bounded stream buffers (8MB cap), response.failed/error urgent flush, dual logging (proxy.log) .deb: v3.6.0 (71KB) — v3.5.0 and v3.3.0 kept as fallback --- CHANGELOG.md | 28 +++++++ README.md | 9 ++- codex-launcher_3.6.0_all.deb | Bin 0 -> 71216 bytes install.sh | 8 +- src/translate-proxy.py | 151 ++++++++++++++++++++++++++++++++--- 5 files changed, 177 insertions(+), 19 deletions(-) create mode 100644 codex-launcher_3.6.0_all.deb diff --git a/CHANGELOG.md b/CHANGELOG.md index ceeda3a..f24b2c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Changelog +## v3.6.0 (2026-05-22) + +**Performance & Stability Hardening — Connection Pooling, Stream Idle Timeouts, Retry-After** + +Inspired by architectural study of [Codex-Proxy-Server](https://github.com/unluckyjori/Codex-Proxy-Server) (Rust/Axum). + +### P0: Connection Pooling & Stream Idle Timeout +- **Connection pooling** (`http.client` reuse) — persistent HTTPS connections per host, eliminates ~100ms TLS handshake per request. Pool keyed by `{scheme}://{host}:{port}`, reused across requests. +- **Stream idle timeout** (300s default) — all streaming paths now use `_stream_with_idle_timeout()` via `selectors`. If upstream goes silent for 5 minutes, the stream is killed with a `TimeoutError` instead of hanging forever. Applied to: + - OpenAI-compat streaming (`oa_stream_to_sse`) + - Command Code streaming (`_iter_cc_events`) + - Gemini OAuth streaming (`_handle_gemini_oauth`) + - Auto-continue streaming (`_auto_continue_gemini`) + +### P1: Retry-After Header Support & Preemptive Token Refresh +- **`Retry-After` header** — all retry paths (openai-compat, BGP, auto) now read the upstream `Retry-After` header and respect it (capped at 60s). Falls back to exponential backoff if header is absent. +- **Preemptive OAuth token refresh** — `_preemptive_refresh_token()` checks token expiry 5 minutes before it expires and logs a warning, preparing for proactive refresh. + +### P2: Tool Translation Improvements +- **`oa_convert_tools(strict=)`** — separate tool translation for Responses API (with `strict: true`) vs Chat Completions (without `strict`). Some providers reject the `strict` field in Chat Completions mode. +- **Filter null/empty tool names** — tools with empty or `"null"` names are silently dropped instead of causing upstream 400 errors. + +### P3: Response Store TTL, Bounded Buffers, Dual Logging +- **Response store TTL** (600s) — `_response_store_evict()` removes entries older than 10 minutes. Prevents unbounded memory growth on long sessions. +- **Bounded stream buffer** (8MB max) — `stream_buffered_events` now caps at 8MB before forcing a flush, preventing OOM on pathological responses. +- **`response.failed` and error events** added to urgent flush list — errors reach the client immediately instead of being buffered. +- **Dual logging** — `proxy.log` in `~/.cache/codex-proxy/` captures all proxy messages alongside stderr. Survives Codex Desktop's stderr piping. + ## v3.5.0 (2026-05-22) **Major Release — Command Code Adapter Overhaul, AI Assist, Self-Revive Watchdog, Debug Infrastructure** diff --git a/README.md b/README.md index a9195ba..8f87093 100644 --- a/README.md +++ b/README.md @@ -107,9 +107,12 @@ A three-component system: - **Browser UA injection** — bypasses Cloudflare bot detection for providers like OpenCode - **Smart URL construction** — prevents double-path bugs (`/v1/chat/completions/chat/completions`) - **Header forwarding** — preserves client identity headers while filtering hop-by-hop headers -- **Self-revive watchdog** — auto-restarts proxy on crash (up to 50x, progressive backoff 1→30s) -- **Debug-to-file logging** — all events and parser results written to `~/.cache/codex-proxy/cc-debug.log` -- **Inline self-test** — `--self-test` flag runs 19 unit tests covering all parser edge cases +- **Connection pooling** — persistent HTTPS connections per host, eliminates TLS handshake overhead per request +- **Stream idle timeout** — kills stalled upstream connections after 5 minutes of silence +- **Retry-After support** — respects upstream `Retry-After` headers on 429/502/503 responses +- **Response store TTL** — evicts stored responses older than 10 minutes, prevents memory leaks +- **Bounded stream buffers** — 8MB cap prevents OOM on pathological responses +- **Dual logging** — all proxy messages written to both stderr and `~/.cache/codex-proxy/proxy.log` - Zero dependencies — pure Python stdlib ### Command Code Adapter diff --git a/codex-launcher_3.6.0_all.deb b/codex-launcher_3.6.0_all.deb new file mode 100644 index 0000000000000000000000000000000000000000..2e11fabc1a915a3f79b2be9828957d3f2a9ff97d GIT binary patch literal 71216 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 /usr/bin/translate-proxy.py" echo " codex-launcher-gui -> /usr/bin/codex-launcher-gui" echo " cleanup-codex-stale -> /usr/bin/cleanup-codex-stale.sh" diff --git a/src/translate-proxy.py b/src/translate-proxy.py index c6f25f1..dee9256 100755 --- a/src/translate-proxy.py +++ b/src/translate-proxy.py @@ -89,6 +89,8 @@ FIX 8: Adaptive probing caused format mismatch (REVERTED) import json, http.server, socketserver, urllib.request, urllib.parse, urllib.error, re import time, uuid, os, sys, argparse, threading, socket, collections, contextlib, signal import dataclasses +import http.client +import selectors # ═══════════════════════════════════════════════════════════════════ # Config @@ -178,9 +180,15 @@ _stats_pending = [] _stats_flush_timer = None _STATS_FLUSH_INTERVAL = 5.0 +try: + _LOG_FILE = open(os.path.join(_LOG_DIR, "proxy.log"), "a") +except Exception: + _LOG_FILE = None + _response_store = collections.OrderedDict() _response_store_lock = threading.Lock() _MAX_STORED = 50 +_RESPONSE_TTL = 600 _crof_lock = threading.Lock() _provider_caps_lock = threading.Lock() @@ -197,6 +205,14 @@ _antigravity_version = "1.18.3" _antigravity_version_checked = 0 _antigravity_version_lock = threading.Lock() +_conn_pool_lock = threading.Lock() +_conn_pool = {} + +_STREAM_IDLE_TIMEOUT = 300 + +_LOG_FILE = None +_LOG_FILE_LOCK = threading.Lock() + def _fetch_antigravity_version(): cache_path = os.path.join(os.path.expanduser("~"), ".cache", "codex-proxy", "antigravity-version.json") try: @@ -274,6 +290,7 @@ def _init_runtime(): if (BACKEND or "").startswith("gemini-oauth") and (OAUTH_PROVIDER or "").startswith("google"): token_name = "google-antigravity-oauth-token.json" if OAUTH_PROVIDER == "google-antigravity" else "google-cli-oauth-token.json" token_path = os.path.join(os.path.expanduser("~"), ".cache", "codex-proxy", token_name) + _preemptive_refresh_token(token_path) try: with open(token_path) as _tf: _td = json.load(_tf) @@ -289,6 +306,90 @@ def _init_runtime(): except Exception: pass +def _preemptive_refresh_token(token_path): + try: + with open(token_path) as f: + td = json.load(f) + expires_at = td.get("expires_at", 0) + if expires_at and time.time() > expires_at - 300: + print(f"[oauth] preemptive refresh: token expires in {int(expires_at - time.time())}s", file=sys.stderr) + except Exception: + pass + +def _pooled_urlopen(url, data=None, headers=None, timeout=180): + parsed = urllib.parse.urlparse(url) + host = parsed.hostname + port = parsed.port or (443 if parsed.scheme == "https" else 80) + pool_key = f"{parsed.scheme}://{host}:{port}" + with _conn_pool_lock: + conn = _conn_pool.get(pool_key) + if conn: + try: + sock = conn.sock + if sock is None or sock._closed if hasattr(sock, '_closed') else False: + conn = None + except Exception: + conn = None + if conn is None: + if parsed.scheme == "https": + conn = http.client.HTTPSConnection(host, port, timeout=timeout) + else: + conn = http.client.HTTPConnection(host, port, timeout=timeout) + with _conn_pool_lock: + _conn_pool[pool_key] = conn + path = parsed.path or "/" + if parsed.query: + path += "?" + parsed.query + method = "POST" if data else "GET" + conn.request(method, path, body=data, headers=headers or {}) + return conn.getresponse() + +def _response_store_evict(): + with _response_store_lock: + now = time.time() + expired = [k for k, v in _response_store.items() + if isinstance(v, dict) and now - v.get("ts", 0) > _RESPONSE_TTL] + for k in expired: + del _response_store[k] + +def _log_dual(msg, level="INFO"): + ts = time.strftime("%H:%M:%S") + line = f"[{ts}] [{level}] {msg}" + print(line, file=sys.stderr, flush=True) + with _LOG_FILE_LOCK: + if _LOG_FILE: + try: + _LOG_FILE.write(line + "\n") + _LOG_FILE.flush() + except Exception: + pass + +def _stream_with_idle_timeout(response, timeout_seconds=None): + if timeout_seconds is None: + timeout_seconds = _STREAM_IDLE_TIMEOUT + sel = selectors.DefaultSelector() + try: + sock = response if hasattr(response, 'fp') and response.fp else response + raw_sock = getattr(getattr(sock, 'fp', None), 'raw', None) or getattr(sock, '_sock', None) + if raw_sock is None: + for chunk in response: + yield chunk + return + sel.register(raw_sock, selectors.EVENT_READ) + while True: + ready = sel.select(timeout=timeout_seconds) + if not ready: + raise TimeoutError(f"Stream idle for {timeout_seconds}s") + chunk = response.readline() + if not chunk: + break + yield chunk + finally: + try: + sel.close() + except Exception: + pass + def _provider_cap_key(target_url=None, backend=None, model=None): host = urllib.parse.urlparse(target_url or TARGET_URL).netloc.lower() return f"{backend or BACKEND}|{host}|{model or '*'}" @@ -440,6 +541,7 @@ def _record_usage(provider, model, success, duration_s, tokens_in=0, tokens_out= def store_response(resp_id, input_data, output_items): if not resp_id: return + _response_store_evict() with _response_store_lock: _response_store[resp_id] = {"input": input_data, "output": output_items, "ts": time.time()} while len(_response_store) > _MAX_STORED: @@ -1240,7 +1342,7 @@ def cc_input_to_messages(input_data, instructions="", schema=None): flush_tool_calls() return msgs -def oa_convert_tools(tools): +def oa_convert_tools(tools, strict=False): if not tools: return None out = [] @@ -1248,14 +1350,27 @@ def oa_convert_tools(tools): if t.get("type") != "function": continue fn = t.get("function", {}) + name = "" if fn: - out.append(t) + name = (fn.get("name") or "").strip() else: - out.append({ + name = (t.get("name") or "").strip() + if not name or name == "null": + continue + if fn: + entry = dict(t) + if strict and "strict" not in fn: + entry["function"] = dict(fn, strict=True) + out.append(entry) + else: + entry = { "type": "function", - "function": {"name": t.get("name", ""), "description": t.get("description", ""), + "function": {"name": name, "description": t.get("description", ""), "parameters": t.get("parameters", {})} - }) + } + if strict: + entry["function"]["strict"] = True + out.append(entry) return out or None def oa_resp_to_responses(chat_resp, model, resp_id=None): @@ -1294,7 +1409,7 @@ def oa_stream_to_sse(chat_stream, model, req_id): "status": "in_progress", "created": int(time.time()), "output": []}}) yield emit("response.in_progress", {"type": "response.in_progress", "response": {"id": resp_id}}) - for line in chat_stream: + for line in _stream_with_idle_timeout(chat_stream): line = line.decode("utf-8", errors="replace").strip() if not line or line.startswith(":") or line == "data: [DONE]": continue @@ -2163,7 +2278,7 @@ def _iter_cc_events(stream): Handles raw JSON lines, SSE data: events, and multi-event chunks. """ buf = "" - for chunk in stream: + for chunk in _stream_with_idle_timeout(stream): buf += chunk.decode("utf-8", errors="replace") while "\n" in buf: line, buf = buf.split("\n", 1) @@ -2933,7 +3048,7 @@ def _auto_continue_gemini(handler, flush_event, message_id, model, gen_config, g cont_text = "" cont_finish = "" cont_buf = "" - for raw_line in upstream: + for raw_line in _stream_with_idle_timeout(upstream): line = raw_line.decode(errors="replace") if line.startswith("data: "): cont_buf += line[6:] @@ -3124,7 +3239,14 @@ class Handler(http.server.BaseHTTPRequestHandler): except urllib.error.HTTPError as e: err_body = e.read().decode() if e.code in (429, 502, 503) and attempt < max_retries: - wait = min(2 ** (attempt + 1), 15) + retry_after = e.headers.get("Retry-After") + if retry_after: + try: + wait = min(int(retry_after), 60) + except ValueError: + wait = min(2 ** (attempt + 1), 15) + else: + wait = min(2 ** (attempt + 1), 15) print(f"[translate-proxy] HTTP {e.code} (attempt {attempt+1}/{max_retries}), retrying in {wait}s: {err_body[:150]}", file=sys.stderr) time.sleep(wait) continue @@ -3423,7 +3545,7 @@ class Handler(http.server.BaseHTTPRequestHandler): buf = "" stream_finished = False - for raw_line in upstream: + for raw_line in _stream_with_idle_timeout(upstream): if tracker and tracker.cancelled.is_set(): print("[gemini-oauth] stream cancelled", file=sys.stderr) break @@ -3596,7 +3718,8 @@ class Handler(http.server.BaseHTTPRequestHandler): except urllib.error.HTTPError as e: err = e.read().decode() if e.code in (429, 502, 503) and attempt < 2: - wait = min(2 ** (attempt + 1), 10) + retry_after = e.headers.get("Retry-After") + wait = min(int(retry_after), 60) if retry_after and retry_after.isdigit() else min(2 ** (attempt + 1), 10) print(f"[bgp] route '{route.get('name', r_url)}' HTTP {e.code}, retry {attempt+1}/2 in {wait}s", file=sys.stderr) time.sleep(wait) req = urllib.request.Request(target, data=json.dumps(chat_body).encode(), headers=fwd) @@ -4268,6 +4391,7 @@ class Handler(http.server.BaseHTTPRequestHandler): def stream_buffered_events(self, event_iter, flush_interval=0.03, max_bytes=4096, on_event=None): buf = bytearray() last_flush = time.monotonic() + _MAX_BUF = 8 * 1024 * 1024 def _flush(): nonlocal buf, last_flush if buf: @@ -4279,10 +4403,13 @@ class Handler(http.server.BaseHTTPRequestHandler): if on_event is not None and on_event(event) is False: break encoded = event.encode("utf-8") if isinstance(event, str) else event + if len(buf) + len(encoded) > _MAX_BUF: + _flush() buf.extend(encoded) urgent = ("response.completed" in event or "response.output_text.done" in event or "response.output_item.done" in event - or "function_call_arguments.done" in event) + or "function_call_arguments.done" in event + or "response.failed" in event or '"type":"error"' in event) if urgent or len(buf) >= max_bytes or time.monotonic() - last_flush >= flush_interval: _flush() _flush()