diff --git a/codex-launcher_3.6.0_all.deb b/codex-launcher_3.6.0_all.deb index 211a9f4..a7e226f 100644 Binary files a/codex-launcher_3.6.0_all.deb and b/codex-launcher_3.6.0_all.deb differ diff --git a/src/translate-proxy.py b/src/translate-proxy.py index dee9256..d60922a 100755 --- a/src/translate-proxy.py +++ b/src/translate-proxy.py @@ -3126,6 +3126,9 @@ class Handler(http.server.BaseHTTPRequestHandler): except Exception as e: return self.send_json(400, {"error": {"message": f"Bad request: {e}"}}) + self._session_id = uuid.uuid4().hex[:8] + _sid = self._session_id + import datetime as _dt _log_path = os.path.join(_LOG_DIR, "requests.log") _ts = _dt.datetime.now().isoformat() @@ -3139,9 +3142,9 @@ class Handler(http.server.BaseHTTPRequestHandler): raw_types = [i.get("type") for i in raw_input] if isinstance(raw_input, list) else "str" resolved_types = [i.get("type") for i in input_data] if isinstance(input_data, list) else "str" - print(f"[REQUEST] prev_id={prev_id} raw={raw_types} resolved={resolved_types}", file=sys.stderr) + print(f"[{_sid}] prev_id={prev_id} raw={raw_types} resolved={resolved_types}", file=sys.stderr) with open(_log_path, "a") as _lf: - _lf.write(f"\n{'='*60}\n{_ts} REQUEST {self.path}\n") + _lf.write(f"\n{'='*60}\n{_ts} [session={_sid}] REQUEST {self.path}\n") _lf.write(f" prev_id={prev_id}\n") _lf.write(f" raw_input_types={raw_types}\n") _lf.write(f" resolved_input_types={resolved_types}\n") @@ -3229,7 +3232,7 @@ class Handler(http.server.BaseHTTPRequestHandler): "Content-Type": "application/json", "Authorization": f"Bearer {effective_key}", }, browser_ua=True) - print(f"[translate-proxy] POST {target} model={model} stream={stream} items={len(input_data) if isinstance(input_data,list) else 1}", file=sys.stderr) + print(f"[{self._session_id}] POST {target} model={model} stream={stream} items={len(input_data) if isinstance(input_data,list) else 1}", file=sys.stderr) chat_body_b = json.dumps(chat_body).encode() max_retries = 3 for attempt in range(max_retries + 1): @@ -3247,14 +3250,14 @@ class Handler(http.server.BaseHTTPRequestHandler): 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) + print(f"[{self._session_id}] HTTP {e.code} (attempt {attempt+1}/{max_retries}), retrying in {wait}s: {err_body[:150]}", file=sys.stderr) time.sleep(wait) continue return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError) as e: if attempt < max_retries: wait = min(2 ** (attempt + 1), 10) - print(f"[translate-proxy] connection error (attempt {attempt+1}/{max_retries}), retrying in {wait}s: {e}", file=sys.stderr) + print(f"[{self._session_id}] connection error (attempt {attempt+1}/{max_retries}), retrying in {wait}s: {e}", file=sys.stderr) time.sleep(wait) continue return self.send_json(502, {"error": {"type": "proxy_error", "message": str(e)}}) @@ -3488,7 +3491,7 @@ class Handler(http.server.BaseHTTPRequestHandler): headers["X-Goog-Api-Client"] = "gl-node/22.17.0" headers["Client-Metadata"] = "ideType=IDE_UNSPECIFIED,platform=PLATFORM_UNSPECIFIED,pluginType=GEMINI" body_b = json.dumps(wrapped).encode() - print(f"[gemini-oauth] model={model} stream={stream} items={len(input_data) if isinstance(input_data, list) else 1} project={project_id}", file=sys.stderr) + print(f"[{self._session_id}] model={model} stream={stream} items={len(input_data) if isinstance(input_data, list) else 1} project={project_id}", file=sys.stderr) for ep in endpoints: target = f"{ep}/{url_suffix}" @@ -3503,17 +3506,17 @@ class Handler(http.server.BaseHTTPRequestHandler): debug_path = os.path.join(_LOG_DIR, "gemini-last-400-request.json") with open(debug_path, "w") as dbg: json.dump({"endpoint": ep, "model": model, "wrapped": wrapped, "error": err_body}, dbg, indent=2) - print(f"[gemini-oauth] saved 400 debug request to {debug_path}", file=sys.stderr) + print(f"[{self._session_id}] saved 400 debug request to {debug_path}", file=sys.stderr) except Exception: pass if e.code == 429 and ep != endpoints[-1]: - print(f"[gemini-oauth] {ep} HTTP 429, trying next endpoint", file=sys.stderr) + print(f"[{self._session_id}] {ep} HTTP 429, trying next endpoint", file=sys.stderr) continue return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) except Exception as e: if ep == endpoints[-1]: return self.send_json(502, {"error": {"type": "proxy_error", "message": str(e)}}) - print(f"[gemini-oauth] {ep} failed: {e}, trying next", file=sys.stderr) + print(f"[{self._session_id}] {ep} failed: {e}, trying next", file=sys.stderr) continue if stream: @@ -3566,10 +3569,10 @@ class Handler(http.server.BaseHTTPRequestHandler): candidates = chunk.get("response", chunk).get("candidates", []) if not candidates: if chunk.get("error"): - print(f"[gemini-oauth] stream error chunk: {str(chunk.get('error'))[:300]}", file=sys.stderr) + print(f"[{self._session_id}] stream error chunk: {str(chunk.get('error'))[:300]}", file=sys.stderr) continue if candidates[0].get("finishReason") and not candidates[0].get("content", {}).get("parts"): - print(f"[gemini-oauth] finish without parts: {candidates[0].get('finishReason')}", file=sys.stderr) + print(f"[{self._session_id}] finish without parts: {candidates[0].get('finishReason')}", file=sys.stderr) parts = candidates[0].get("content", {}).get("parts", []) for part in parts: if part.get("thought"): @@ -3598,7 +3601,7 @@ class Handler(http.server.BaseHTTPRequestHandler): last_finish = candidates[0].get("finishReason", "") if OAUTH_PROVIDER == "google-antigravity" and full_text and last_finish: if last_finish == "MAX_TOKENS" and not current_tool_calls: - print(f"[gemini-oauth] MAX_TOKENS hit ({len(full_text)} chars), auto-continuing...", file=sys.stderr) + print(f"[{self._session_id}] MAX_TOKENS hit ({len(full_text)} chars), auto-continuing...", file=sys.stderr) break stream_finished = True break @@ -3704,14 +3707,14 @@ class Handler(http.server.BaseHTTPRequestHandler): "Content-Type": "application/json", "Authorization": f"Bearer {r_key}", }, browser_ua=True) - print(f"[bgp] trying route '{route.get('name', r_url)}' model={r_model}", file=sys.stderr) + print(f"[{self._session_id}] trying route '{route.get('name', r_url)}' model={r_model}", file=sys.stderr) req = urllib.request.Request(target, data=json.dumps(chat_body).encode(), headers=fwd) t0_route = time.time() route_ok = False for attempt in range(3): try: upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, stream)) - print(f"[bgp] route '{route.get('name', r_url)}' connected OK", file=sys.stderr) + print(f"[{self._session_id}] route '{route.get('name', r_url)}' connected OK", file=sys.stderr) _update_route_stats(route, True, time.time() - t0_route) self._forward_oa_compat(upstream, stream, r_model, chat_body, body, input_data, fwd, target) return @@ -3720,18 +3723,18 @@ class Handler(http.server.BaseHTTPRequestHandler): if e.code in (429, 502, 503) and attempt < 2: 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) + print(f"[{self._session_id}] 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) continue - print(f"[bgp] route '{route.get('name', r_url)}' FAILED: HTTP {e.code}: {err[:200]}", file=sys.stderr) + print(f"[{self._session_id}] route '{route.get('name', r_url)}' FAILED: HTTP {e.code}: {err[:200]}", file=sys.stderr) _update_route_stats(route, False, time.time() - t0_route, http_code=e.code) errors.append(f"{route.get('name','?')}: HTTP {e.code}") break except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError) as e: if attempt < 2: wait = min(2 ** (attempt + 1), 8) - print(f"[bgp] route '{route.get('name', r_url)}' conn error, retry {attempt+1}/2 in {wait}s: {e}", file=sys.stderr) + print(f"[{self._session_id}] route '{route.get('name', r_url)}' conn error, retry {attempt+1}/2 in {wait}s: {e}", file=sys.stderr) time.sleep(wait) req = urllib.request.Request(target, data=json.dumps(chat_body).encode(), headers=fwd) continue @@ -3739,12 +3742,12 @@ class Handler(http.server.BaseHTTPRequestHandler): errors.append(f"{route.get('name','?')}: {e}") break except Exception as e: - print(f"[bgp] route '{route.get('name', r_url)}' FAILED: {e}", file=sys.stderr) + print(f"[{self._session_id}] route '{route.get('name', r_url)}' FAILED: {e}", file=sys.stderr) _update_route_stats(route, False, time.time() - t0_route, error_type=str(e)) errors.append(f"{route.get('name','?')}: {e}") break - print(f"[bgp] ALL ROUTES FAILED: {errors}", file=sys.stderr) + print(f"[{self._session_id}] ALL ROUTES FAILED: {errors}", file=sys.stderr) self.send_json(502, {"error": {"type": "bgp_all_routes_failed", "message": f"All BGP routes failed: {'; '.join(errors)}"}}) def _forward_oa_compat(self, upstream, stream, model, chat_body, body, input_data, fwd, target, tracker=None): @@ -4022,7 +4025,7 @@ class Handler(http.server.BaseHTTPRequestHandler): } fwd = forwarded_headers(self.headers, headers_extra, browser_ua=True) - print(f"[translate-proxy] POST {target} model={model} stream={stream} attempt={attempt} [command-code]", file=sys.stderr) + print(f"[{self._session_id}] POST {target} model={model} stream={stream} attempt={attempt} [command-code]", file=sys.stderr) req = urllib.request.Request( target, data=json.dumps(cc_body).encode(), @@ -4037,7 +4040,7 @@ class Handler(http.server.BaseHTTPRequestHandler): if attempt < max_retries: hints = ErrorAnalyzer.analyze(err, schema) if hints: - print(f"[command-code] error analysis: {hints}", file=sys.stderr) + print(f"[{self._session_id}] error analysis: {hints}", file=sys.stderr) ErrorAnalyzer.merge_into_schema(hints, schema) _save_schema(schema, model=model) continue @@ -4083,7 +4086,7 @@ class Handler(http.server.BaseHTTPRequestHandler): try: self.stream_buffered_events(cc_stream_to_sse(upstream, model, body.get("request_id") or body.get("id")), on_event=on_event) except Exception as e: - print(f"[command-code] stream error: {e}", file=sys.stderr) + print(f"[{self._session_id}] stream error: {e}", file=sys.stderr) try: err_event = 'data: ' + json.dumps({"type": "response.completed", "response": {"id": body.get("request_id") or body.get("id") or uid("resp"), @@ -4416,7 +4419,7 @@ class Handler(http.server.BaseHTTPRequestHandler): def log_message(self, fmt, *args): msg = fmt % args if args else fmt - print(f"[translate-proxy] {BACKEND} {msg}", file=sys.stderr) + print(f"[{self._session_id}] {BACKEND} {msg}", file=sys.stderr) _SHUTDOWN_REQUESTED = False