From 256b1ac08b798eaacd2f99e8da3665c7caa136bd Mon Sep 17 00:00:00 2001 From: Roman | RyzenAdvanced Date: Tue, 26 May 2026 18:16:16 +0400 Subject: [PATCH] v3.11.6: fix auth os error 2 handling, rebuild deb --- codex-launcher_3.11.5_all.deb | Bin 156116 -> 0 bytes codex-launcher_3.11.6_all.deb | Bin 157812 -> 158050 bytes translate-proxy.py | 7483 --------------------------------- 3 files changed, 7483 deletions(-) delete mode 100644 codex-launcher_3.11.5_all.deb delete mode 100755 translate-proxy.py diff --git a/codex-launcher_3.11.5_all.deb b/codex-launcher_3.11.5_all.deb deleted file mode 100644 index 4fff7570f7891c2abb4c136f80a90f6db080a398..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 156116 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∾TW{SV@a-(h{md4g) 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�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

?G;?dRanHb^*)3Q&` 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 W>|*9wD1uG!2w$~17Zn6%AQJ}VSotad diff --git a/codex-launcher_3.11.6_all.deb b/codex-launcher_3.11.6_all.deb index edc0e5c8712b7f807076d60ff86156be68262416..2e943d865964538a8ad794562ceab32ba564a1df 100644 GIT binary patch delta 141246 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 delta 140968 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 diff --git a/translate-proxy.py b/translate-proxy.py deleted file mode 100755 index 6c5906b..0000000 --- a/translate-proxy.py +++ /dev/null @@ -1,7483 +0,0 @@ -#!/usr/bin/env python3 -""" -translate-proxy.py — Responses API → backend API translation proxy. - -Backends: - openai-compat — any OpenAI-compatible Chat Completions API - anthropic — Anthropic Messages API - command-code — CommandCode /alpha/generate (Z.AI GLM Coding Plan) - -Usage: - python3 translate-proxy.py --config proxy-config.json - python3 translate-proxy.py --backend command-code --target-url https://... --api-key sk-... - -═══════════════════════════════════════════════════════════════════ -COMMANDCODE ADAPTER — FIX HISTORY (2026-05-22) -═══════════════════════════════════════════════════════════════════ - -This file contains multiple rounds of fixes for the CommandCode adapter. -Each fix addresses a specific failure mode observed in production. -They are documented here for future maintainability. - -FIX 1: Content blocks rejected by CC API (root cause of initial 400 errors) - Symptom: {"error":{"message":"params.messages[i].content expected string, received array"}} - Cause: cc_input_to_messages emitted tool results as content blocks [{"type":"tool_result",...}] - Fix: All messages now use string content. Tool results as role="user" with plain text. - Location: cc_input_to_messages() ~line 1085 - -FIX 2: x-command-code-version header dropped during rewrite - Symptom: HTTP 403 upgrade_required from CommandCode API - Cause: _handle_command_code rewrite removed the header line - Fix: Always send x-command-code-version header with fallback "0.26.8" - Location: _handle_command_code() header setup block - -FIX 3: Stale schema cache with wrong content_type=array - Symptom: SchemaAdapter used content_type="array" causing content blocks in auto path - Cause: ErrorAnalyzer learned incorrect schema from error message text - Fix: Cleared provider-caps.json; added 24h staleness TTL to _load_schema() - Location: _load_schema(), provider-caps.json - -FIX 4: Stream disconnect before completion (client-side "stream disconnected") - Symptom: Client sees partial SSE then connection close, no response.completed event - Cause: No try/except around streaming path; exceptions crashed handler mid-stream - Fix: Wrapped stream_buffered_events in try/except; sends response.completed(status:"failed") on crash - Location: _handle_command_code() streaming section - -FIX 5: Tool calls echoed as text instead of being parsed (THE BIG ONE) - Symptom: Model generates inline JSON tool calls like {"type":"tool-call","id":"...","name":"exec_command","arguments":"{...}"} - These appear as raw text in the conversation. The tool is never executed. - Root cause chain: - a) cc_input_to_messages sends tool calls as inline JSON text in assistant messages - b) The CC model echoes back similar JSON in its text-delta response - c) _parse_commandcode_text_tool_calls only handled XML format (``` -``) - d) Raw JSON tool calls passed through as plain text → client shows them unparsed - Fix: Added _extract_raw_json_tool_calls() with field-level regex extraction. - Handles BOTH malformed (unescaped inner quotes) AND properly escaped JSON. - Three-tier parse: direct json.loads → unescape \"→\" → unicode_escape decode. - Location: _extract_args(), _extract_field(), _extract_raw_json_tool_calls() - -FIX 6: Double-wrapped arguments (nested {"cmd": "{\"cmd\": \"curl...\"}"}") - Symptom: args={"cmd": "{\\\"cmd\\\": \\\"curl...\\\"}"} - Tool executor receives cmd = the literal string '{"cmd": "curl..."', not the actual curl command. - Root cause: When model generates properly escaped JSON ("arguments": "{\\"cmd\\": \\"...\\"}"), - _extract_args naive brace-counting returns raw text with escaped quotes. - json.loads(raw) fails on \\ at structural level. - Fallback sets args["cmd"] = raw_string → double-wrapped. - Fix: _extract_args now tries 3 parse strategies before returning. - Also normalizes sandbox_permissions from parsed args dict (not raw snippet). - Location: _extract_args() three-tier parser, sandbox_permissions normalization - -FIX 7: _extract_field can't read values starting with \" - Symptom: sandbox_permissions="allow_all" passes through unnormalized because - _extract_field sees val_start=\\ (backslash) which != \" or { → returns None - Fix: Skip leading backslash before checking for " or { value type. - Location: _extract_field() leading-backslash skip - -FIX 8: Adaptive probing caused format mismatch (REVERTED) - Symptom: Probe system discovered OpenAI tool_calls+role=tool format but CC API couldn't - process multi-turn tool loops correctly with it. - Fix: Removed probe system entirely. Use conservative format only: - - Inline JSON text for tool calls (cc_input_to_messages default) - - role="user" for all tool results - - ErrorAnalyzer learning on retries (not proactive probes) - Location: Reverted to cc_input_to_messages(), removed _build_cc_messages + _probe_cc_format - -FIX 21: DSML parser silently drops tool calls when model uses name="cmd" (THE HALT BUG) - Symptom: Codex CLI stops mid-task. Model generates valid DSML exec_command with - <||DSML||parameter name="cmd" string="true">curl ... - Parser returns parsed_tool_calls=0. Client sees text output but no tool to execute. - CLI has nothing to do and halts. - Root cause: Line 1798 had `if key == "command":` — only matching parameter name="command". - The actual tool schema defines the parameter as "cmd" (see exec_command schema). - When DeepSeek generates name="cmd", the key "cmd" != "command", so cmd stays None, - and line 1825-1826 `if not cmd: continue` silently skips the entire tool call. - The XML parser (line 2205) already handled both: `params.get("command") or params.get("cmd")` - but the DSML parser did not. - Fix: Changed to `if key in ("command", "cmd"):` in the DSML parameter loop. - Test: Pattern L self-test verifies DSML with name="cmd" is parsed correctly. - Location: _parse_commandcode_text_tool_calls() DSML parameter loop, self-test Pattern L - -════════════════════════════════════════════════════════════════════ -INTELLIGENCE ROUTING — Self-Healing Parser System (v3.7.0) -════════════════════════════════════════════════════════════════════ - -Problem: The Command Code model produces output in unpredictable formats -that change between sessions and models. When the multi-format parser chain -(DSML → → XML → raw JSON → -fallback regex) returns empty, the Codex agent loop has zero tool calls and -STALLS — the user sees the model "thinking" but nothing happens. - -Intelligence Routing is a three-layer self-healing system: - -LAYER 1 — Deep URL Extraction (FIX 23) - The handler was failing because URLs were hidden inside - nested JSON: messages: [{"content": "https://..."}]. The regex couldn't - find them because it excluded the " character that terminates JSON values. - - Solution: _build_explore_cmd() is now a module-level function (was a - closure). After the initial regex fails, it tries json.loads() on the - text, iterates list items, and extracts the "content" field to find URLs. - Also added " to the regex exclusion set and rstrip characters. - -LAYER 2 — Escalation Block Handling (FIX 24) - The model produces and - blocks when it wants elevated permissions. The CC adapter doesn't support - escalation — these blocks were silently dropped, causing parsed_tool_calls=0. - - Solution: Two handlers: - - FIX 24a: Closed-tag blocks — extracts URL if present, runs explore cmd; - otherwise echoes auto-proceed message. - - FIX 24b: Bare/unclosed tags () — auto-proceeds. - -LAYER 3 — Intent-Based Command Synthesis (FIX 25, THE CORE) - When ALL parsers return empty and text has content, the system plays - detective using 5 heuristics in priority order: - - 1. URL detected in text → curl to fetch it - 2. File path reference → cat or ls that file - 3. Shell command in backticks/quotes → extract and run - 4. "explore"/"fetch"/"investigate" intent + last user URL → explore cmd - 5. "I need to"/"let me"/"please" intent text → echo diagnostic - - This ensures the agent loop ALWAYS has a tool call to execute, even when - the model's output format is completely unrecognized. The loop never stalls. - -Architecture: - _parse_commandcode_text_tool_calls() — LAYER 1 + LAYER 2 - cc_stream_to_sse() — LAYER 3 (runs after parser chain + fallback) - - The _last_user_urls deque (maxlen=20) tracks URLs from user messages - across the session, giving Layer 3 heuristic 4 a URL to work with. - - Self-tests: 54 patterns (was 41) covering all three layers. - -════════════════════════════════════════════════════════════════════ -""" - -import json, http.server, socketserver, urllib.request, urllib.parse, urllib.error, re -import time, uuid, os, sys, argparse, threading, socket, collections, contextlib, signal -import secrets, string -import dataclasses -import http.client -import selectors -import tempfile - -_IS_WINDOWS = sys.platform == "win32" - -# ═══════════════════════════════════════════════════════════════════ -# Config -# ═══════════════════════════════════════════════════════════════════ - -DEFAULT_MODELS = { - "openai-compat": [ - {"id": "gpt-4o-mini", "object": "model", "created": 1700000000, "owned_by": "custom"}, - ], - "anthropic": [ - {"id": "claude-sonnet-4-20250514", "object": "model", "created": 1700000000, "owned_by": "anthropic"}, - ], - "codebuff": [ - {"id": "deepseek/deepseek-v4-pro", "object": "model", "created": 1700000000, "owned_by": "codebuff"}, - {"id": "deepseek/deepseek-v4-flash", "object": "model", "created": 1700000000, "owned_by": "codebuff"}, - {"id": "moonshotai/kimi-k2.6", "object": "model", "created": 1700000000, "owned_by": "codebuff"}, - {"id": "minimax/minimax-m2.7", "object": "model", "created": 1700000000, "owned_by": "codebuff"}, - ], - "auto": [ - {"id": "default-model", "object": "model", "created": 1700000000, "owned_by": "auto"}, - ], -} - -def load_config(): - global _CONFIG_PATH, _CONFIG_MTIME - p = argparse.ArgumentParser(description="Responses API translation proxy") - p.add_argument("--config", help="JSON config file path") - p.add_argument("--port", type=int, default=None) - p.add_argument("--backend", default=None, choices=["openai-compat", "anthropic", "command-code", "codebuff", "freebuff", "auto"]) - p.add_argument("--target-url", default=None) - p.add_argument("--api-key", default=None) - p.add_argument("--models-file", default=None, help="JSON file with model list array") - _args = p.parse_args() - - cfg = {} - if _args.config: - _CONFIG_PATH = os.path.abspath(_args.config) - with open(_args.config) as f: - cfg = json.load(f) - try: - _CONFIG_MTIME = os.path.getmtime(_CONFIG_PATH) - except OSError: - pass - - for ck, ak in [("port", "port"), ("backend_type", "backend"), - ("target_url", "target_url"), ("api_key", "api_key")]: - v = getattr(_args, ak, None) - if v is not None: - cfg[ck] = v - - env_map = { - "port": ("PROXY_PORT", "ZAI_PROXY_PORT", int), - "backend_type": ("PROXY_BACKEND", None, str), - "target_url": ("PROXY_TARGET_URL", "ZAI_BASE_URL", str), - "api_key": ("PROXY_API_KEY", "ZAI_API_KEY", str), - } - for ck, (ev1, ev2, conv) in env_map.items(): - if ck not in cfg: - v = os.environ.get(ev1) or (os.environ.get(ev2) if ev2 else None) - if v: - cfg[ck] = conv(v) if conv == int else v - - cfg.setdefault("port", 8080) - cfg.setdefault("backend_type", "openai-compat") - cfg.setdefault("target_url", "http://localhost:11434/v1") - cfg.setdefault("api_key", "") - - models = cfg.get("models", []) - if not models and _args.models_file: - with open(_args.models_file) as f: - models = json.load(f) - if not models: - models = DEFAULT_MODELS.get(cfg["backend_type"], []) - cfg["models"] = models - - return cfg - -CONFIG = None -_CONFIG_PATH = None -_CONFIG_MTIME = 0 -PORT = 8080 -BACKEND = "openai-compat" -TARGET_URL = "" -API_KEY = "" -OAUTH_PROVIDER = "" -MODELS = [] -CC_VERSION = "" -REASONING_ENABLED = True -REASONING_EFFORT = "medium" -FORCE_MODEL = "" -BGP_ROUTES = [] -PROMPT_ENHANCER = False -PROMPT_ENHANCER_MODE = "offline" -PROMPT_ENHANCER_MODEL = "" -PROMPT_ENHANCER_URL = "" -PROMPT_ENHANCER_KEY = "" -SERVER = None - -if _IS_WINDOWS: - _LOG_DIR = os.path.join(os.environ.get("LOCALAPPDATA", os.path.expanduser("~")), "codex-proxy") -else: - _LOG_DIR = os.path.join(os.path.expanduser("~"), ".cache", "codex-proxy") -os.makedirs(_LOG_DIR, exist_ok=True) -_REQUESTS_DIR = os.path.join(_LOG_DIR, "requests") -os.makedirs(_REQUESTS_DIR, exist_ok=True) -try: - for _f in os.listdir(_REQUESTS_DIR): - if _f.endswith(".tmp"): - os.remove(os.path.join(_REQUESTS_DIR, _f)) -except Exception: - pass -_stats_path = os.path.join(_LOG_DIR, "usage-stats.json") -_provider_caps_path = os.path.join(_LOG_DIR, "provider-caps.json") -_stats_lock = threading.Lock() -_stats_pending = [] -_stats_flush_timer = None -_STATS_FLUSH_INTERVAL = 5.0 -_STATS = {} - -try: - _LOG_FILE = open(os.path.join(_LOG_DIR, "proxy.log"), "a", encoding="utf-8") -except Exception: - _LOG_FILE = None - -_response_store = collections.OrderedDict() -_response_store_lock = threading.Lock() -_MAX_STORED = 50 -_RESPONSE_TTL = 600 - -_fb_reasoning_store = collections.OrderedDict() -_fb_reasoning_store_lock = threading.Lock() - -_deepseek_reasoning_store = {} -_deepseek_reasoning_lock = threading.Lock() -_MAX_DS_STORED = 100 - -_last_reasoning_store = {} -_last_reasoning_lock = threading.Lock() - -_crof_lock = threading.Lock() -_provider_caps_lock = threading.Lock() -_provider_caps = None - -_shutdown_requested = False -_active_connections = 0 -_active_connections_lock = threading.Lock() -_active_requests = {} -_active_requests_lock = threading.Lock() - -_pool = uuid.uuid4().hex[:8] -_antigravity_version = "1.18.3" -_antigravity_version_checked = 0 -_antigravity_version_lock = threading.Lock() -_last_user_urls = collections.deque(maxlen=20) - -_conn_pool_lock = threading.Lock() -_conn_pool = {} - -_STREAM_IDLE_TIMEOUT = 300 -_MAX_CONCURRENT_REQUESTS = 3 -_request_semaphore = threading.Semaphore(_MAX_CONCURRENT_REQUESTS) - -_CODEBUFF_AUTH_URL = "https://www.codebuff.com" -_CODEBUFF_API_URL = "https://www.codebuff.com" -_CODEBUFF_AGENT_MAP = { - "deepseek/deepseek-v4-pro": "base2-free-deepseek", - "deepseek/deepseek-v4-flash": "base2-free-deepseek-flash", - "moonshotai/kimi-k2.6": "base2-free-kimi", - "minimax/minimax-m2.7": "base2-free", -} -if _IS_WINDOWS: - _CODEBUFF_CREDS_PATH = os.path.join(os.environ.get("APPDATA", os.path.expanduser("~")), "manicode", "credentials.json") -else: - _CODEBUFF_CREDS_PATH = os.path.join(os.path.expanduser("~"), ".config", "manicode", "credentials.json") -_codebuff_token_cache = {"token": None, "checked": 0} -_codebuff_session_cache = {"instance_id": None, "expires": 0, "model": None} -_codebuff_token_lock = threading.Lock() - -def _get_codebuff_token(): - with _codebuff_token_lock: - if _codebuff_token_cache["token"] and _codebuff_token_cache["checked"] > time.time() - 300: - return _codebuff_token_cache["token"] - try: - with open(_CODEBUFF_CREDS_PATH) as f: - creds = json.load(f) - default_account = creds.get("default", {}) - token = default_account.get("authToken") or creds.get("apiKey") or "" - with _codebuff_token_lock: - _codebuff_token_cache["token"] = token - _codebuff_token_cache["checked"] = time.time() - return token - except Exception as e: - print(f"[codebuff] no credentials at {_CODEBUFF_CREDS_PATH}: {e}", file=sys.stderr) - return "" - -def _codebuff_get_session(token, model): - with _codebuff_token_lock: - sc = _codebuff_session_cache - if sc["instance_id"] and sc["expires"] > time.time() + 60 and sc["model"] == model: - return sc["instance_id"] - try: - url = f"{_CODEBUFF_API_URL}/api/v1/freebuff/session" - body = json.dumps({}).encode() - req = urllib.request.Request(url, data=body, headers={ - "Content-Type": "application/json", - "Authorization": f"Bearer {token}", - "User-Agent": "ai-sdk/openai-compatible/1.0.25/codebuff", - "x-codebuff-model": model, - }) - try: - resp = urllib.request.urlopen(req, timeout=15) - except urllib.error.HTTPError as e: - err_body = e.read().decode()[:1000] - if e.code == 429: - retry_s = 120 - user_msg = "" - try: - err_data = json.loads(err_body) - retry_ms = err_data.get("retryAfterMs", 0) - if retry_ms: - retry_s = retry_ms / 1000 - user_msg = err_data.get("message", err_data.get("error", "")) - if isinstance(user_msg, dict): - user_msg = user_msg.get("message", "") - except Exception: - pass - if not user_msg: - user_msg = _sanitize_err_body(err_body) - raise RateLimitError(retry_s, user_msg) - print(f"[codebuff] session HTTP {e.code}: {err_body[:200]}", file=sys.stderr) - return None - data = json.loads(resp.read()) - instance_id = data.get("instanceId", data.get("data", {}).get("instance_id", "")) - expires_at = data.get("remainingMs", 0) - if instance_id: - with _codebuff_token_lock: - _codebuff_session_cache["instance_id"] = instance_id - _codebuff_session_cache["expires"] = time.time() + min(expires_at / 1000, 3600) - _codebuff_session_cache["model"] = model - print(f"[codebuff] session active, instance={instance_id[:8]}...", file=sys.stderr) - return instance_id - return None - except RateLimitError: - raise - except Exception as e: - print(f"[codebuff] session failed: {e}", file=sys.stderr) - return None - -def _codebuff_start_run(token, agent_id): - url = f"{_CODEBUFF_API_URL}/api/v1/agent-runs" - body = json.dumps({"action": "START", "agentId": agent_id, "ancestorRunIds": []}).encode() - req = urllib.request.Request(url, data=body, headers={ - "Content-Type": "application/json", - "Authorization": f"Bearer {token}", - "User-Agent": "ai-sdk/openai-compatible/1.0.25/codebuff", - }) - try: - resp = urllib.request.urlopen(req, timeout=15) - data = json.loads(resp.read()) - run_id = data.get("runId") - print(f"[codebuff] started run {run_id} for agent {agent_id}", file=sys.stderr) - return run_id, None - except urllib.error.HTTPError as e: - err = e.read().decode()[:500] - print(f"[codebuff] start run failed: HTTP {e.code}: {err}", file=sys.stderr) - if e.code == 429: - retry_s = 120 - try: - err_data = json.loads(err) - retry_ms = err_data.get("retryAfterMs", 0) - if retry_ms: - retry_s = retry_ms / 1000 - except Exception: - pass - return None, ("rate_limit_error", 429, retry_s, _sanitize_err_body(err)) - return None, ("upstream_error", e.code, 0, _sanitize_err_body(err)) - except Exception as e: - print(f"[codebuff] start run error: {e}", file=sys.stderr) - return None, ("proxy_error", 502, 0, str(e)) - -def _codebuff_finish_run(token, run_id, status="completed"): - url = f"{_CODEBUFF_API_URL}/api/v1/agent-runs" - body = json.dumps({"action": "FINISH", "runId": run_id, "status": status, - "totalSteps": 1, "directCredits": 0, "totalCredits": 0}).encode() - req = urllib.request.Request(url, data=body, headers={ - "Content-Type": "application/json", - "Authorization": f"Bearer {token}", - "User-Agent": "ai-sdk/openai-compatible/1.0.25/codebuff", - }) - try: - urllib.request.urlopen(req, timeout=10) - except Exception as e: - print(f"[codebuff] finish run {run_id} error: {e}", file=sys.stderr) - -# ═══════════════════════════════════════════════════════════════════ -# Multi-account rotation system -class RateLimitError(Exception): - def __init__(self, retry_seconds, message=""): - self.retry_seconds = retry_seconds - self.message = message - super().__init__(f"rate-limited for {retry_seconds:.0f}s: {message}") - -# ═══════════════════════════════════════════════════════════════════ - -class AccountPool: - """Manages multiple accounts for a provider. Rotates on rate-limit (429/426).""" - - def __init__(self, provider_name): - self.provider_name = provider_name - self._lock = threading.Lock() - self._accounts = [] - self._rate_limited = {} - self._current_idx = 0 - self._loaded_at = 0 - - def load_accounts(self, force=False): - with self._lock: - if not force and self._accounts and time.time() - self._loaded_at < 60: - return len(self._accounts) - accounts = self._do_load() - with self._lock: - if accounts: - self._accounts = accounts - self._loaded_at = time.time() - for a in accounts: - key = a.get("id", a.get("email", "")) - if key not in self._rate_limited: - self._rate_limited[key] = 0 - return len(self._accounts) if accounts else 0 - - def _do_load(self): - return [] - - def get(self): - """Return the best available account dict, or None.""" - self.load_accounts() - with self._lock: - if not self._accounts: - return None - now = time.time() - n = len(self._accounts) - for attempt in range(n): - idx = (self._current_idx + attempt) % n - acct = self._accounts[idx] - key = acct.get("id", acct.get("email", "")) - if self._rate_limited.get(key, 0) < now: - self._current_idx = idx - return acct - best_key = min(self._rate_limited, key=self._rate_limited.get) - wait = self._rate_limited[best_key] - now - print(f"[{self.provider_name}] all accounts rate-limited, earliest free in {wait:.0f}s", file=sys.stderr) - return self._accounts[self._current_idx] - - def mark_rate_limited(self, account, duration=120): - key = account.get("id", account.get("email", "")) - with self._lock: - self._rate_limited[key] = time.time() + duration - idx = None - for i, a in enumerate(self._accounts): - if a.get("id", a.get("email", "")) == key: - idx = i - break - if idx is not None: - self._current_idx = (idx + 1) % len(self._accounts) - print(f"[{self.provider_name}] account {key} rate-limited for {duration}s, rotating to next", file=sys.stderr) - - def advance(self): - with self._lock: - if self._accounts: - self._current_idx = (self._current_idx + 1) % len(self._accounts) - - def status(self): - with self._lock: - now = time.time() - result = [] - for a in self._accounts: - key = a.get("id", a.get("email", "")) - rl_until = self._rate_limited.get(key, 0) - info = {"id": key, "email": a.get("email", ""), "rate_limited": rl_until > now} - if rl_until > now: - info["rate_limited_until"] = rl_until - info["resets_in"] = int(rl_until - now) - result.append(info) - return result - -class CodebuffAccountPool(AccountPool): - def _do_load(self): - if not os.path.exists(_CODEBUFF_CREDS_PATH): - return None - try: - with open(_CODEBUFF_CREDS_PATH) as f: - creds = json.load(f) - except Exception: - return None - accounts = [] - if "accounts" in creds and isinstance(creds["accounts"], list): - for i, ac in enumerate(creds["accounts"]): - token = ac.get("authToken") or ac.get("apiKey") or "" - if token: - acct = {"id": ac.get("email") or ac.get("id") or f"account-{i}", "token": token, "email": ac.get("email", "")} - accounts.append(acct) - default = creds.get("default", {}) - default_token = default.get("authToken") or creds.get("apiKey") or "" - if default_token: - default_id = default.get("email") or default.get("id") or "default" - if not any(a["id"] == default_id for a in accounts): - accounts.insert(0, {"id": default_id, "token": default_token, "email": default.get("email", "")}) - return accounts if accounts else None - -class GoogleAccountPool(AccountPool): - def __init__(self, variant): - super().__init__(f"google-{variant}") - self.variant = variant - - def _do_load(self): - cache_dir = os.path.join(os.path.expanduser("~"), ".cache", "codex-proxy") - accounts = [] - primary = f"google-{self.variant}-oauth-token.json" - primary_path = os.path.join(cache_dir, primary) - if os.path.exists(primary_path): - try: - with open(primary_path) as f: - tok = json.load(f) - token = tok.get("access_token", "") - if token: - accounts.append({"id": f"google-{self.variant}-primary", "token": token, "email": tok.get("email", ""), "_token_data": tok, "_path": primary_path}) - except Exception: - pass - idx = 1 - while True: - extra = f"google-{self.variant}-oauth-token-{idx}.json" - extra_path = os.path.join(cache_dir, extra) - if not os.path.exists(extra_path): - break - try: - with open(extra_path) as f: - tok = json.load(f) - token = tok.get("access_token", "") - if token: - accounts.append({"id": f"google-{self.variant}-{idx}", "token": token, "email": tok.get("email", ""), "_token_data": tok, "_path": extra_path}) - except Exception: - pass - idx += 1 - return accounts if accounts else None - -class APIKeyPool(AccountPool): - """Rotates through comma-separated API keys.""" - - def __init__(self, provider_name, keys_str): - super().__init__(provider_name) - self._raw_keys = [k.strip() for k in keys_str.split(",") if k.strip()] - self._accounts = [{"id": f"key-{i}", "token": k, "email": f"key-{i}"} for i, k in enumerate(self._raw_keys)] - for a in self._accounts: - self._rate_limited[a["id"]] = 0 - self._loaded_at = time.time() - - def load_accounts(self, force=False): - return len(self._accounts) - -_cb_pool = CodebuffAccountPool("codebuff") -_google_antigravity_pool = GoogleAccountPool("antigravity") -_google_cli_pool = GoogleAccountPool("cli") -_antigravity_preferred_endpoint = None -_antigravity_endpoint_lock = threading.Lock() - -def _classify_antigravity_error(status_code, body): - lower = body.lower() - if status_code == 400: - return "bad_request" - if status_code == 401: - if any(x in lower for x in ["invalid_grant", "token revoked", "token_revoked", "invalid_client"]): - return "auth_permanent" - return "auth_transient" - if status_code == 403: - if "validation_required" in lower or "account_disabled" in lower: - return "validation_required" - if "has been disabled" in lower and "violation of terms of service" in lower: - return "account_banned" - if "service_disabled" in lower: - return "service_disabled" - return "forbidden" - if status_code in (429, 503, 529): - if any(x in lower for x in ["model_capacity_exhausted", "capacity_exhausted", "model is currently overloaded", "service temporarily unavailable"]): - return "capacity_exhausted" - if any(x in lower for x in ["quota_exhausted", "resource_exhausted", "daily limit", "quota exceeded", "quotaresetdelay"]): - return "quota_exhausted" - return "rate_limited" - if status_code >= 500: - return "server_error" - return "unknown" - -def _parse_rate_limit_reset(body): - import re as _re - m = _re.search(r'quotaResetDelay[:"\s]+(\d+(?:\.\d+)?)(ms|s)', body, _re.IGNORECASE) - if m: - val = float(m.group(1)) - return val / 1000 if m.group(2) == 'ms' else val - m = _re.search(r'(\d+)h(\d+)m(\d+)s', body, _re.IGNORECASE) - if m: - return int(m.group(1)) * 3600 + int(m.group(2)) * 60 + int(m.group(3)) - m = _re.search(r'Resets in ~(\d+)h(\d+)m', body, _re.IGNORECASE) - if m: - return int(m.group(1)) * 3600 + int(m.group(2)) * 60 - m = _re.search(r'retry[-_]?after[:\s]+(\d+)\s*(?:sec|s\b)', body, _re.IGNORECASE) - if m: - return int(m.group(1)) - return None - -def _get_codebuff_account(): - """Return (token, account_dict) for best available codebuff account.""" - _cb_pool.load_accounts() - acct = _cb_pool.get() - if not acct: - return "", None - return acct["token"], acct - -def _get_google_account(oauth_provider): - """Return (access_token, account_dict) for best available Google account.""" - pool = _google_antigravity_pool if oauth_provider == "google-antigravity" else _google_cli_pool - pool.load_accounts() - acct = pool.get() - if not acct: - return None, None - token_data = acct.get("_token_data", {}) - token_path = acct.get("_path", "") - if token_data and token_path: - refreshed = _refresh_google_token(token_data, token_path) - return refreshed, acct - return acct.get("token", ""), acct - -def _refresh_google_token(token_data, token_path): - if token_data.get("expires_at", 0) > time.time() + 60: - return token_data.get("access_token", "") - client_id = token_data.get("client_id", "") - client_secret = token_data.get("client_secret", "") - refresh_token = token_data.get("refresh_token", "") - if not all([client_id, client_secret, refresh_token]): - return token_data.get("access_token", "") - print("[oauth] refreshing Google access token...", file=sys.stderr) - try: - data = urllib.parse.urlencode({ - "client_id": client_id, "client_secret": client_secret, - "refresh_token": refresh_token, "grant_type": "refresh_token", - }).encode() - req = urllib.request.Request("https://oauth2.googleapis.com/token", data=data, - headers={"Content-Type": "application/x-www-form-urlencoded"}) - resp = urllib.request.urlopen(req, timeout=30) - new_tokens = json.loads(resp.read()) - token_data["access_token"] = new_tokens.get("access_token", token_data.get("access_token")) - token_data["expires_at"] = time.time() + new_tokens.get("expires_in", 3600) - with open(token_path, "w", encoding="utf-8") as f: - json.dump(token_data, f, indent=2) - print("[oauth] token refreshed OK", file=sys.stderr) - return token_data["access_token"] - except Exception as e: - print(f"[oauth] refresh failed: {e}", file=sys.stderr) - return token_data.get("access_token", "") - -# ═══════════════════════════════════════════════════════════════════ -# Gemini 3 thought signature preservation -# ═══════════════════════════════════════════════════════════════════ - -_gemini_sig_store = {} -_gemini_sig_lock = threading.Lock() - -def _gemini_store_sig(key, signature): - if not key or not signature: - return - with _gemini_sig_lock: - _gemini_sig_store[key] = {"sig": signature, "ts": time.time()} - -def _gemini_get_sig(key): - with _gemini_sig_lock: - item = _gemini_sig_store.get(key) - return item["sig"] if item else None - -def _extract_gemini_sig(part): - if not isinstance(part, dict): - return None - return part.get("thoughtSignature") or part.get("thought_signature") or part.get("signature") - -def _gemini_reattach_sigs(contents): - for content in contents: - for part in content.get("parts", []): - if not isinstance(part, dict): - continue - if "thoughtSignature" in part: - continue - if "functionCall" in part: - fc = part["functionCall"] - cid = fc.get("id") or fc.get("name") - if cid: - sig = _gemini_get_sig(f"fc:{cid}") - if sig: - part["thoughtSignature"] = sig - if "text" in part and content.get("role") == "model": - turn_key = content.get("_proxy_turn_key") - if turn_key: - sig = _gemini_get_sig(f"turn:{turn_key}") - if sig: - part["thoughtSignature"] = sig - return contents - -# Gemini follow-through guardrail -_GEMINI_AGENT_GUARDRAIL = ( - "!!! ABSOLUTELY CRITICAL - DO NOT IGNORE THIS UNDER ANY CIRCUMSTANCES !!! " - "YOU ARE RUNNING INSIDE CODEX AS AN AUTONOMOUS CODING AGENT. " - "!!!!!! NEVER EVER CONTINUE, PARAPHRASE, COMPLETE, OR ADD ANYTHING TO THE USER'S INSTRUCTIONS !!!!!! " - "!!!!!! NEVER SAY 'LET\\'S FIRST VIEW' OR 'LET\\'S FIRST FIND' OR SIMILAR PHRASES - EMIT THE ACTUAL TOOL CALL NOW !!!!!! " - "WHEN THE USER ASKS FOR A CHANGE TO EXISTING FILES, YOU MUST " - "1. IMMEDIATELY INSPECT EXISTING FILES USING exec_command OR read_files TOOLS RIGHT NOW, " - "2. THEN APPLY EDITS USING write OR exec_command TOOLS, " - "3. THEN VERIFY THE RESULT. " - "IF A FILE PATH IS KNOWN, REUSE IT IMMEDIATELY. " - "IF UNSURE, LIST FILES FIRST USING exec_command (ls -la). " - "AFTER TOOL RESULTS, CONTINUE UNTIL THE REQUESTED CHANGE IS FULLY IMPLEMENTED AND FILES ARE MODIFIED. " - "NEVER ANSWER ONLY WITH A PLAN LIKE 'I WILL START BY...' OR 'I AM GOING TO...'. " - "NEVER SUMMARIZE THE USER'S REQUEST. NEVER CONTINUE THEIR SENTENCE. " - "ALWAYS, ALWAYS, ALWAYS EMIT THE ACTUAL TOOL CALL IN THE SAME RESPONSE. " - "!!! FAILURE TO FOLLOW THESE INSTRUCTIONS WILL RESULT IN A BROKEN USER EXPERIENCE !!!" -) - -_LOG_FILE_LOCK = threading.Lock() -_ANTIGRAVITY_LOOP_TRACKER = {} -_ANTIGRAVITY_LOOP_TRACKER_LOCK = threading.Lock() -def _antigravity_loop_key(session_id): - return f"ag:{session_id}" - -def _fetch_antigravity_version(): - cache_path = os.path.join(os.path.expanduser("~"), ".cache", "codex-proxy", "antigravity-version.json") - try: - with open(cache_path) as f: - cached = json.load(f) - if cached.get("version") and cached.get("checked_at", 0) > time.time() - 6 * 3600: - return cached["version"] - except Exception: - pass - urls = [ - ("https://antigravity-auto-updater-974169037036.us-central1.run.app", None), - ("https://antigravity.google/changelog", 5000), - ] - for url, limit in urls: - try: - req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}) - resp = urllib.request.urlopen(req, timeout=5) - text = resp.read().decode(errors="replace") - if limit: - text = text[:limit] - m = re.search(r"\d+\.\d+\.\d+", text) - if m: - version = m.group(0) - try: - os.makedirs(os.path.dirname(cache_path), exist_ok=True) - with open(cache_path, "w", encoding="utf-8") as f: - json.dump({"version": version, "checked_at": time.time()}, f) - except Exception: - pass - return version - except Exception: - pass - return _antigravity_version - -def _ensure_antigravity_version(): - global _antigravity_version, _antigravity_version_checked - if time.time() - _antigravity_version_checked < 6 * 3600: - return _antigravity_version - with _antigravity_version_lock: - if time.time() - _antigravity_version_checked < 6 * 3600: - return _antigravity_version - _antigravity_version = _fetch_antigravity_version() - _antigravity_version_checked = time.time() - return _antigravity_version - -_antigravity_client_version = "1.110.0" -_antigravity_client_version_checked = 0 - -def _ensure_antigravity_client_version(): - global _antigravity_client_version, _antigravity_client_version_checked - env_ver = os.environ.get("ANTIGRAVITY_CLIENT_VERSION", "").strip() - if env_ver: - return env_ver - if time.time() - _antigravity_client_version_checked < 6 * 3600: - return _antigravity_client_version - _antigravity_client_version = os.environ.get("ANTIGRAVITY_CLIENT_VERSION_FALLBACK", "1.110.0") - _antigravity_client_version_checked = time.time() - return _antigravity_client_version - -def _init_runtime(): - global CONFIG, PORT, BACKEND, TARGET_URL, API_KEY, OAUTH_PROVIDER, _antigravity_version - global MODELS, CC_VERSION, REASONING_ENABLED, REASONING_EFFORT, BGP_ROUTES - global _api_key_pool, PROMPT_ENHANCER - - CONFIG = load_config() - PORT = CONFIG["port"] - BACKEND = CONFIG["backend_type"] - TARGET_URL = CONFIG["target_url"].rstrip("/") - API_KEY = CONFIG["api_key"] - OAUTH_PROVIDER = CONFIG.get("oauth_provider") or "" - MODELS = CONFIG["models"] - CC_VERSION = CONFIG.get("cc_version", "") - REASONING_ENABLED = CONFIG.get("reasoning_enabled", True) - REASONING_EFFORT = CONFIG.get("reasoning_effort", "medium") - FORCE_MODEL = (CONFIG.get("force_model") or "").strip() - PROMPT_ENHANCER = CONFIG.get("prompt_enhancer", False) - PROMPT_ENHANCER_MODE = CONFIG.get("prompt_enhancer_mode", "offline") - PROMPT_ENHANCER_MODEL = CONFIG.get("prompt_enhancer_model", "") - PROMPT_ENHANCER_URL = CONFIG.get("prompt_enhancer_url", "") - PROMPT_ENHANCER_KEY = CONFIG.get("prompt_enhancer_key", "") - BGP_ROUTES = CONFIG.get("bgp_routes", []) - _api_key_pool = None - if API_KEY and "," in API_KEY and not OAUTH_PROVIDER.startswith("google") and BACKEND not in ("codebuff", "freebuff"): - _api_key_pool = APIKeyPool(BACKEND, API_KEY) - print(f"[multi-account] API key pool: {len(_api_key_pool._accounts)} keys for {BACKEND}", file=sys.stderr) - if OAUTH_PROVIDER == "google-antigravity": - _antigravity_version = _ensure_antigravity_version() - print(f"[antigravity] version={_antigravity_version}", file=sys.stderr) - -def _verify_api_key(key, target_url): - if not key or not target_url: - return {"valid": False, "error": "missing key or url"} - test_url = upstream_target(target_url, "/models") - if not test_url: - return {"valid": False, "error": "invalid target url"} - try: - req = urllib.request.Request(test_url, headers={ - "Authorization": f"Bearer {key}", - "Content-Type": "application/json", - }) - resp = urllib.request.urlopen(req, timeout=10) - body = resp.read().decode() - model_count = 0 - try: - data = json.loads(body) - model_count = len(data.get("data", [])) - except Exception: - pass - return {"valid": True, "status": resp.status, "models": model_count} - except urllib.error.HTTPError as e: - err = e.read().decode()[:200] - return {"valid": False, "status": e.code, "error": err} - except Exception as e: - return {"valid": False, "error": str(e)[:200]} - -_HOT_RELOAD_LOCK = threading.Lock() - -def _hot_reload_api_key(): - global API_KEY, _api_key_pool, _CONFIG_MTIME - if not _CONFIG_PATH: - return False - try: - cur_mtime = os.path.getmtime(_CONFIG_PATH) - except OSError: - return False - if cur_mtime <= _CONFIG_MTIME: - return False - with _HOT_RELOAD_LOCK: - try: - cur_mtime2 = os.path.getmtime(_CONFIG_PATH) - if cur_mtime2 <= _CONFIG_MTIME: - return False - with open(_CONFIG_PATH) as f: - new_cfg = json.load(f) - new_key = (new_cfg.get("api_key") or "").strip() - if not new_key or new_key == API_KEY: - _CONFIG_MTIME = cur_mtime2 - return False - old_preview = API_KEY[:8] + "..." if len(API_KEY) > 8 else "(empty)" - new_preview = new_key[:8] + "..." if len(new_key) > 8 else "(empty)" - API_KEY = new_key - _CONFIG_MTIME = cur_mtime2 - if API_KEY and "," in API_KEY and not OAUTH_PROVIDER.startswith("google") and BACKEND not in ("codebuff", "freebuff"): - _api_key_pool = APIKeyPool(BACKEND, API_KEY) - print(f"[hot-reload] API key pool refreshed: {len(_api_key_pool._accounts)} keys", file=sys.stderr) - print(f"[hot-reload] API key updated: {old_preview} -> {new_preview}", file=sys.stderr) - return True - except Exception as e: - print(f"[hot-reload] error: {e}", file=sys.stderr) - return False - - bgp_models = [] - for _r in BGP_ROUTES: - for _m in _r.get("models", [{"id": _r.get("model", "unknown")}]): - mid = _m.get("id", _m) if isinstance(_m, dict) else _m - if mid not in bgp_models: - bgp_models.append(mid) - if BGP_ROUTES and not MODELS: - MODELS = [{"id": m, "object": "model", "created": 1700000000, "owned_by": "bgp"} for m in bgp_models] - CONFIG["models"] = MODELS - - 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) - _discovered = [] if OAUTH_PROVIDER == "google-antigravity" else _td.get("available_models", []) - if _discovered: - _seen = [] - for _m in _discovered: - if _m not in _seen: - _seen.append(_m) - MODELS = [{"id": m, "object": "model", "created": 1700000000, "owned_by": "gemini-oauth"} for m in _seen] - CONFIG["models"] = MODELS - print(f"[gemini-oauth] loaded {len(_seen)} discovered models: {_seen}", file=sys.stderr) - 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 '*'}" - -def _load_provider_caps(): - global _provider_caps - with _provider_caps_lock: - if _provider_caps is not None: - return _provider_caps - try: - with open(_provider_caps_path) as f: - _provider_caps = json.load(f) - except Exception: - _provider_caps = {} - return _provider_caps - -def _save_provider_caps(): - try: - os.makedirs(os.path.dirname(_provider_caps_path), exist_ok=True) - with open(_provider_caps_path, "w", encoding="utf-8") as f: - json.dump(_provider_caps or {}, f, indent=2) - except Exception as e: - print(f"[provider-sensor] failed to save caps: {e}", file=sys.stderr) - -def _provider_cap(model, key, default=None): - caps = _load_provider_caps() - specific = caps.get(_provider_cap_key(model=model), {}) - generic = caps.get(_provider_cap_key(model="*"), {}) - return specific.get(key, generic.get(key, default)) - -def _set_provider_cap(model, key, value, reason=""): - caps = _load_provider_caps() - cap_key = _provider_cap_key(model=model) - caps.setdefault(cap_key, {})[key] = value - caps[cap_key]["reason"] = reason - caps[cap_key]["updated_at"] = time.time() - _save_provider_caps() - print(f"[provider-sensor] learned {cap_key}: {key}={value} reason={reason}", file=sys.stderr) - -def _refresh_oauth_token(): - return _refresh_oauth_token_for(API_KEY, OAUTH_PROVIDER) - -def _refresh_oauth_token_for(api_key, oauth_provider): - oauth_provider = oauth_provider or "" - if oauth_provider.startswith("google"): - token, acct = _get_google_account(oauth_provider) - if token and acct: - return token - if not oauth_provider.startswith("google"): - return api_key - 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) - if not os.path.exists(token_path): - return api_key - try: - with open(token_path) as f: - tokens = json.load(f) - if tokens.get("expires_at", 0) > time.time() + 60: - return tokens.get("access_token", api_key) - client_id = tokens.get("client_id", "") - client_secret = tokens.get("client_secret", "") - refresh_token = tokens.get("refresh_token", "") - if not all([client_id, client_secret, refresh_token]): - return tokens.get("access_token", api_key) - print("[oauth] refreshing Google access token...", file=sys.stderr) - data = urllib.parse.urlencode({ - "client_id": client_id, "client_secret": client_secret, - "refresh_token": refresh_token, "grant_type": "refresh_token", - }).encode() - req = urllib.request.Request("https://oauth2.googleapis.com/token", data=data, - headers={"Content-Type": "application/x-www-form-urlencoded"}) - resp = urllib.request.urlopen(req, timeout=30) - new_tokens = json.loads(resp.read()) - tokens["access_token"] = new_tokens.get("access_token", tokens.get("access_token")) - tokens["expires_at"] = time.time() + new_tokens.get("expires_in", 3600) - with open(token_path, "w", encoding="utf-8") as f: - json.dump(tokens, f, indent=2) - print("[oauth] token refreshed OK", file=sys.stderr) - return tokens["access_token"] - except Exception as e: - print(f"[oauth] refresh failed: {e}", file=sys.stderr) - return API_KEY - -# ═══════════════════════════════════════════════════════════════════ -# Shared helpers -# ═══════════════════════════════════════════════════════════════════ - -_pool = uuid.uuid4().hex[:8] - -def _load_stats(): - try: - if os.path.exists(_stats_path): - return json.load(open(_stats_path)) - except Exception: - pass - return {"providers": {}, "updated": None} - -def _atomic_write_json(path, obj): - tmp = path + ".tmp" - with open(tmp, "w", encoding="utf-8") as f: - json.dump(obj, f, indent=2, ensure_ascii=False) - os.replace(tmp, path) - -def _flush_stats(): - global _stats_flush_timer - with _stats_lock: - batch = list(_stats_pending) - _stats_pending.clear() - _stats_flush_timer = None - if not batch: - return - stats = _load_stats() - for entry in batch: - provider = entry["provider"] - model = entry["model"] - p = stats["providers"].setdefault(provider, { - "total_requests": 0, "successes": 0, "failures": 0, - "total_tokens_in": 0, "total_tokens_out": 0, - "total_duration_s": 0.0, "models": {}, "last_used": None, "last_error": None, - }) - p["total_requests"] += 1 - p["total_tokens_in"] += entry["tokens_in"] - p["total_tokens_out"] += entry["tokens_out"] - p["total_duration_s"] += entry["duration_s"] - p["last_used"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(entry["ts"])) - if entry["success"]: - p["successes"] += 1 - else: - p["failures"] += 1 - p["last_error"] = entry.get("error_type") or "unknown" - m = p["models"].setdefault(model, {"requests": 0, "tokens_in": 0, "tokens_out": 0}) - m["requests"] += 1 - m["tokens_in"] += entry["tokens_in"] - m["tokens_out"] += entry["tokens_out"] - stats["updated"] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) - _atomic_write_json(_stats_path, stats) - -def _record_usage(provider, model, success, duration_s, tokens_in=0, tokens_out=0, error_type=None): - global _stats_flush_timer - entry = { - "provider": provider or "unknown", "model": model or "unknown", - "success": bool(success), "duration_s": float(duration_s or 0), - "tokens_in": int(tokens_in or 0), "tokens_out": int(tokens_out or 0), - "error_type": error_type, "ts": time.time(), - } - with _stats_lock: - _stats_pending.append(entry) - if _stats_flush_timer is None: - _stats_flush_timer = threading.Timer(_STATS_FLUSH_INTERVAL, _flush_stats) - _stats_flush_timer.daemon = True - _stats_flush_timer.start() - -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: - _response_store.popitem(last=False) - -def resolve_previous_response(body): - prev_id = body.get("previous_response_id") - input_data = body.get("input", "") - if not prev_id: - return input_data - with _response_store_lock: - stored = _response_store.get(prev_id) - if not stored: - return input_data - prev_input = stored["input"] - prev_output = stored["output"] - new_input = input_data if isinstance(input_data, list) else [] - if isinstance(prev_input, list): - combined = list(prev_input) + list(prev_output) + new_input - else: - combined = [{"type": "message", "role": "user", "content": [{"type": "input_text", "text": str(prev_input)}]}] + list(prev_output) + new_input - return combined - -def _fb_store_reasoning(resp_id, reasoning_text): - if not resp_id or not reasoning_text: - return - with _fb_reasoning_store_lock: - _fb_reasoning_store[resp_id] = {"reasoning": reasoning_text, "ts": time.time()} - while len(_fb_reasoning_store) > _MAX_STORED: - _fb_reasoning_store.popitem(last=False) - expired = [k for k, v in _fb_reasoning_store.items() if time.time() - v["ts"] > _RESPONSE_TTL] - for k in expired: - del _fb_reasoning_store[k] - -def _fb_get_reasoning(resp_id): - if not resp_id: - return "" - with _fb_reasoning_store_lock: - entry = _fb_reasoning_store.get(resp_id) - return entry["reasoning"] if entry else "" - -def _fb_get_any_reasoning(): - with _fb_reasoning_store_lock: - for k in _fb_reasoning_store: - return _fb_reasoning_store[k]["reasoning"] - return "" - -def _codebuff_hard_disable_reasoning(messages): - """Strip all reasoning/thinking fields from every message. - Codebuff rejects mixed reasoning_content histories. - The final chat body must be clean before POST.""" - for msg in messages: - if not isinstance(msg, dict): - continue - for key in ("reasoning_content", "reasoning", "thinking", - "thinking_content", "thoughts"): - msg.pop(key, None) - -def _is_reasoning_content_error(error_text): - if not error_text: - return False - e = error_text.lower() - return ("reasoning_content" in e or "thinking mode" in e - or "must be passed back" in e) - -def _ds_store_assistant(resp_id, assistant_msg): - if not resp_id or not isinstance(assistant_msg, dict): - return - tool_calls = assistant_msg.get("tool_calls") or [] - reasoning = assistant_msg.get("reasoning_content") - if not tool_calls or not reasoning: - return - with _deepseek_reasoning_lock: - for tc in tool_calls: - tc_id = tc.get("id") or tc.get("call_id", "") - if tc_id: - _deepseek_reasoning_store[tc_id] = { - "resp_id": resp_id, - "assistant": dict(assistant_msg), - "reasoning_content": reasoning, - "ts": time.time(), - } - keys = list(_deepseek_reasoning_store.keys()) - if len(keys) > _MAX_DS_STORED: - for k in keys[:len(keys) - _MAX_DS_STORED]: - del _deepseek_reasoning_store[k] - -def _ds_rebuild_tool_history(messages): - with _deepseek_reasoning_lock: - snapshot = dict(_deepseek_reasoning_store) - expired = [k for k, v in snapshot.items() if time.time() - v["ts"] > 900] - for k in expired: - _deepseek_reasoning_store.pop(k, None) - snapshot.pop(k, None) - if not snapshot: - return messages - rebuilt = [] - inserted_ids = set() - for msg in messages: - if msg.get("role") == "tool": - tc_id = msg.get("tool_call_id", "") - stored = snapshot.get(tc_id) - if stored and tc_id not in inserted_ids: - am = dict(stored["assistant"]) - if am.get("reasoning_content"): - rebuilt.append(am) - inserted_ids.add(tc_id) - rebuilt.append(msg) - return rebuilt - -def _cb_input_to_messages(input_data, instructions=""): - msgs = [] - tool_name_by_id = {} - pending_tool_calls = [] - last_flushed_ids = [] - if isinstance(input_data, str): - msgs.append({"role": "user", "content": input_data}) - elif isinstance(input_data, list): - for item in input_data: - t = item.get("type") - if t == "reasoning": - continue - if t == "function_call": - tcid = item.get("call_id") or item.get("id") or uid("tc") - pending_tool_calls.append( - {"id": tcid, "type": "function", - "function": {"name": item.get("name", ""), - "arguments": item.get("arguments", "{}")}}) - tool_name_by_id[tcid] = item.get("name", "") - continue - if pending_tool_calls: - last_flushed_ids = [tc["id"] for tc in pending_tool_calls] - msg = {"role": "assistant", "content": None, "tool_calls": pending_tool_calls} - msgs.append(msg) - pending_tool_calls = [] - if t == "message": - role = item.get("role", "user") - if role == "developer": - role = "system" - text = "" - content = item.get("content", []) - if isinstance(content, str): - text = content - else: - for part in content: - if isinstance(part, str): - text += part - continue - pt = part.get("type", "") - if pt in ("input_text", "output_text"): - text += part.get("text", "") - if text is not None: - am = {"role": role, "content": text} - if role == "assistant": - am["_fb_orig_id"] = item.get("id", "") - msgs.append(am) - elif t == "function_call_output": - tcid = item.get("call_id") or item.get("id") or "" - if not tcid and last_flushed_ids: - idx = len([m for m in msgs if m.get("role") == "tool"]) - if idx < len(last_flushed_ids): - tcid = last_flushed_ids[idx] - msgs.append({"role": "tool", "tool_call_id": tcid, - "tool_name": tool_name_by_id.get(tcid, ""), - "content": item.get("output", "")}) - if pending_tool_calls: - msg = {"role": "assistant", "content": None, "tool_calls": pending_tool_calls} - msgs.append(msg) - if instructions: - msgs.insert(0, {"role": "system", "content": instructions}) - return msgs - -def _fb_strip_reasoning_from_messages(messages): - out = [] - for m in messages: - nm = {k: v for k, v in m.items() if k != "reasoning_content"} - out.append(nm) - return out - -_HOP_BY_HOP_HEADERS = { - "connection", - "keep-alive", - "proxy-authenticate", - "proxy-authorization", - "te", - "trailers", - "transfer-encoding", - "upgrade", - "host", - "content-length", -} - -def uid(prefix="id"): - return f"{prefix}-{_pool}-{uuid.uuid4().hex[:12]}" - -def emit(event, data): - return f"event: {event}\ndata: {json.dumps(data)}\n\n" - -def upstream_target(base_url, suffix): - base = base_url.rstrip("/") - if base.endswith(suffix): - return base - return f"{base}{suffix}" - -_BROWSER_HEADERS = { - "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36", - "Accept": "application/json, text/event-stream, */*", - "Accept-Language": "en-US,en;q=0.9", - "Sec-Ch-Ua": '"Chromium";v="137", "Not/A)Brand";v="99"', - "Sec-Ch-Ua-Mobile": "?0", - "Sec-Ch-Ua-Platform": '"Linux"', - "Sec-Fetch-Dest": "empty", - "Sec-Fetch-Mode": "cors", - "Sec-Fetch-Site": "same-origin", -} - -def forwarded_headers(request_headers, extra=None, browser_ua=False): - headers = {} - if browser_ua: - headers.update(_BROWSER_HEADERS) - for key, value in request_headers.items(): - if key.lower() in _HOP_BY_HOP_HEADERS: - continue - if browser_ua and key.lower() == "user-agent": - continue - headers[key] = value - if extra: - headers.update(extra) - return headers - -def _openrouter_extra(): - if not TARGET_URL: - return {} - if "z.ai" in TARGET_URL: - return { - "HTTP-Referer": "https://openclaw.ai", - "X-OpenRouter-Title": "OpenClaw", - "X-OpenRouter-Categories": - "cli-agent,cloud-agent,programming-app,creative-writing," - "writing-assistant,general-chat,personal-agent", - } - if "openrouter.ai" in TARGET_URL: - return { - "HTTP-Referer": "https://chats-llm.com", - "X-OpenRouter-Title": "Chats-LLM", - "X-OpenRouter-Categories": "general-chat, ide-extension", - "X-OpenRouter-Cache": "true", - } - return {} - -_MAX_INPUT_ITEMS = 30 -_MAX_TOOL_OUTPUT_CHARS = 8000 -_COMPACT_KEEP_RECENT = 10 - -_CROF_ADAPTIVE = { - "fail_history": [], - "model_limits": {}, - "global_item_limit": 80, - "min_keep_recent": 6, -} - -_model_max_tokens = {} -_model_max_tokens_lock = threading.Lock() - -def _estimate_tokens(item): - if not isinstance(item, dict): - return 4 - t = item.get("type", "") - if t == "message": - content = item.get("content", "") - if isinstance(content, str): - return max(4, len(content) // 4) - elif isinstance(content, list): - total = 4 - for part in content: - pt = part.get("type", "") - if pt in ("input_text", "output_text"): - total += max(4, len(part.get("text", "")) // 4) - elif pt == "input_image": - total += 800 - elif pt in ("function_call",): - total += max(20, len(part.get("arguments", "{}")) // 2) - elif pt == "function_call_output": - total += max(8, len(part.get("output", "")) // 4) - return total - elif t in ("function_call_output",): - return max(8, len(item.get("output", "")) // 4) - elif t == "function_call": - return max(20, len(item.get("arguments", "{}")) // 2) - return 4 - -def _estimate_input_tokens(input_data): - if not isinstance(input_data, list): - return 0 - return sum(_estimate_tokens(i) for i in input_data) - -def _get_model_max_tokens(model): - with _model_max_tokens_lock: - return _model_max_tokens.get(model) - -def _set_model_max_tokens(model, tokens): - if model and tokens: - with _model_max_tokens_lock: - existing = _model_max_tokens.get(model) - if existing is None or tokens < existing: - _model_max_tokens[model] = tokens - print(f"[ctx-limit] learned {model} max ~{tokens} tokens", file=sys.stderr) - -_BGP_STATS_PATH = os.path.join(_LOG_DIR, "bgp-route-stats.json") -_bgp_stats_lock = threading.Lock() - -def _route_key(route): - return f"{route.get('name', '')}::{route.get('target_url', '')}::{route.get('model', '')}" - -def _load_bgp_stats(): - try: - if os.path.exists(_BGP_STATS_PATH): - return json.load(open(_BGP_STATS_PATH)) - except Exception: - pass - return {} - -def _save_bgp_stats(stats): - tmp = _BGP_STATS_PATH + ".tmp" - with open(tmp, "w", encoding="utf-8") as f: - json.dump(stats, f, indent=2) - os.replace(tmp, _BGP_STATS_PATH) - -def _score_route(route, stats): - key = _route_key(route) - rs = stats.get(key, {}) - now = time.time() - if float(rs.get("open_until_ts", 0)) > now: - return 1_000_000 - priority = int(route.get("priority", 99)) - ewma = float(rs.get("ewma_latency_s", 0)) - failures = int(rs.get("consecutive_failures", 0)) - score = priority + min(ewma * 5, 50) + failures * 20 - if float(rs.get("rate_limited_until", 0)) > now: - score += 500 - return score - -def _update_route_stats(route, success, duration_s, http_code=None, error_type=None): - with _bgp_stats_lock: - stats = _load_bgp_stats() - key = _route_key(route) - rs = stats.setdefault(key, { - "ewma_latency_s": duration_s, "consecutive_failures": 0, - "last_success": None, "last_failure": None, - "open_until_ts": 0, "rate_limited_until": 0, "last_error": None, - }) - alpha = 0.25 - rs["ewma_latency_s"] = alpha * duration_s + (1 - alpha) * float(rs.get("ewma_latency_s", duration_s)) - if success: - rs["consecutive_failures"] = 0 - rs["last_success"] = time.time() - else: - rs["consecutive_failures"] = int(rs.get("consecutive_failures", 0)) + 1 - rs["last_failure"] = time.time() - rs["last_error"] = error_type or (f"http_{http_code}" if http_code else "unknown") - if http_code == 429: - rs["rate_limited_until"] = time.time() + 120 - if rs["consecutive_failures"] >= 3: - rs["open_until_ts"] = time.time() + 60 - rs["consecutive_failures"] = 0 - _save_bgp_stats(stats) - -def _sorted_bgp_routes(): - with _bgp_stats_lock: - stats = _load_bgp_stats() - return sorted(BGP_ROUTES, key=lambda r: _score_route(r, stats)) - -def _crof_record(model, n_items, success): - if not isinstance(n_items, int) or n_items < 1: - return - entry = {"model": model, "items": n_items, "ok": success} - hist = _CROF_ADAPTIVE["fail_history"] - hist.append(entry) - if len(hist) > 200: - _CROF_ADAPTIVE["fail_history"] = hist[-100:] - - ml = _CROF_ADAPTIVE["model_limits"].setdefault(model, {"ok_max": 30, "fail_min": 0, "limit": 30}) - if success and n_items > ml["ok_max"]: - ml["ok_max"] = n_items - if not success and (ml["fail_min"] == 0 or n_items < ml["fail_min"]): - ml["fail_min"] = n_items - - if ml["fail_min"] > 0 and ml["ok_max"] >= ml["fail_min"]: - ml["limit"] = ml["fail_min"] - 1 - elif ml["fail_min"] > 0: - ml["limit"] = max(ml["fail_min"] - 2, _CROF_ADAPTIVE["min_keep_recent"] + 2) - - global_limit = 30 - for m, v in _CROF_ADAPTIVE["model_limits"].items(): - if v.get("limit", 30) < global_limit: - global_limit = v["limit"] - _CROF_ADAPTIVE["global_item_limit"] = global_limit - - print(f"[crof-adaptive] model={model} items={n_items} {'OK' if success else 'FAIL'} -> limit={ml.get('limit',30)} global={global_limit}", file=sys.stderr) - -def _crof_item_limit(model): - ml = _CROF_ADAPTIVE["model_limits"].get(model, {}) - per_model = ml.get("limit", 30) - return min(per_model, _CROF_ADAPTIVE["global_item_limit"]) - -def _crof_compact_for_retry(input_data, model, aggression=0): - limit = _crof_item_limit(model) - if not isinstance(input_data, list) or len(input_data) < 2: - return input_data - - max_tok = _get_model_max_tokens(model) - est = _estimate_input_tokens(input_data) - over_item_limit = len(input_data) > limit - over_token_limit = max_tok and est >= max_tok * 0.9 - - if not over_item_limit and not over_token_limit: - return input_data - - keep = max(_CROF_ADAPTIVE["min_keep_recent"], limit // 3) - if over_token_limit: - ratio = est / max_tok - if aggression >= 1 or ratio > 1.5: - keep = max(2, _CROF_ADAPTIVE["min_keep_recent"] // 2) - elif ratio > 1.2: - keep = max(3, keep // 2) - print(f"[ctx-limit] model={model} est={est}tok max={max_tok}tok ratio={ratio:.2f} -> keep={keep}", file=sys.stderr) - elif over_item_limit: - keep = max(keep, 6) - head_end = 0 - for i, item in enumerate(input_data): - t = item.get("type") - if t == "message" and item.get("role") in ("developer", "system"): - head_end = i + 1 - elif t == "message" and item.get("role") == "user" and head_end == i: - head_end = i + 1 - else: - break - - head = input_data[:head_end] - tail_start = max(head_end, len(input_data) - keep) - while tail_start > head_end: - t = input_data[tail_start].get("type") - r = input_data[tail_start].get("role", "") - if t in ("function_call_output", "function_call"): - tail_start -= 1 - elif t == "message" and r == "assistant": - tail_start -= 1 - else: - break - tail = input_data[tail_start:] - body = input_data[head_end:tail_start] - - if not body: - return head + tail - - summary_lines = [f"[Auto-compacted: {len(body)} turns removed (adaptive limit={limit})]"] - for item in body[-5:]: - summary_lines.append(_item_summary(item, max_len=120)) - - summary_msg = {"type": "message", "role": "user", "content": [{"type": "input_text", "text": "\n".join(summary_lines)}]} - print(f"[crof-adaptive] RETRY compact: {len(input_data)} -> {len(head)+1+len(tail)} (limit={limit}, keep={len(tail)}, agg={aggression})", file=sys.stderr) - return head + [summary_msg] + tail - -def _item_summary(item, max_len=200): - t = item.get("type") - if t == "message": - role = item.get("role", "?") - text = "" - for p in item.get("content", []): - if p.get("type") in ("input_text", "output_text"): - text += p.get("text", "") - return f"[{role}] {text[:max_len]}" - elif t == "function_call": - name = item.get("name", "?") - args = item.get("arguments", "{}") - try: - a = json.loads(args) - cmd = a.get("cmd", a.get("command", "")) - if cmd: - return f"[tool call] {name}: {cmd[:max_len]}" - except Exception: - pass - return f"[tool call] {name}({args[:max_len]})" - elif t == "function_call_output": - output = item.get("output", "") - if len(output) > max_len: - return f"[tool result] {output[:max_len]}..." - return f"[tool result] {output}" - return f"[{t}]" - -def _extract_files(items): - files = set() - for item in items: - if item.get("type") == "function_call": - try: - a = json.loads(item.get("arguments", "{}")) - cmd = a.get("cmd", a.get("command", "")) - for prefix in (">", ">>", " > ", " >> "): - for part in cmd.split(prefix)[1:]: - f = part.strip().split()[0].strip("'\"") - if f and not f.startswith("-") and "/" in f: - files.add(f) - except Exception: - pass - return files - -def _compact_input(input_data): - if isinstance(input_data, str): - return input_data - if not isinstance(input_data, list) or len(input_data) <= _MAX_INPUT_ITEMS: - out = [] - for item in input_data: - if isinstance(item, dict) and item.get("type") == "function_call_output": - o = item.get("output", "") - if len(o) > _MAX_TOOL_OUTPUT_CHARS: - item = dict(item) - item["output"] = o[:_MAX_TOOL_OUTPUT_CHARS] + f"\n... [truncated {len(o) - _MAX_TOOL_OUTPUT_CHARS} chars]" - print(f"[compact] tool output truncated {len(o)} -> {_MAX_TOOL_OUTPUT_CHARS}", file=sys.stderr) - out.append(item) - return out - - head_end = 0 - for i, item in enumerate(input_data): - t = item.get("type") - if t == "message" and item.get("role") in ("developer", "system"): - head_end = i + 1 - elif t == "message" and item.get("role") == "user" and head_end == i: - head_end = i + 1 - else: - break - - head = input_data[:head_end] - tail_start = len(input_data) - _COMPACT_KEEP_RECENT - while tail_start > head_end: - t = input_data[tail_start].get("type") - r = input_data[tail_start].get("role", "") - if t == "function_call_output": - tail_start -= 1 - elif t == "function_call": - tail_start -= 1 - elif t == "message" and r == "assistant": - tail_start -= 1 - else: - break - tail = input_data[tail_start:] - body = input_data[head_end:tail_start] - - if not body: - return head + tail - - for item in tail: - if isinstance(item, dict) and item.get("type") == "function_call_output": - o = item.get("output", "") - if len(o) > _MAX_TOOL_OUTPUT_CHARS: - item["output"] = o[:_MAX_TOOL_OUTPUT_CHARS] + f"\n... [truncated {len(o) - _MAX_TOOL_OUTPUT_CHARS} chars]" - - user_queries = [] - for item in body: - if item.get("type") == "message" and item.get("role") == "user": - for p in item.get("content", []): - if p.get("type") == "input_text": - user_queries.append(p.get("text", "")[:300]) - assistant_msgs = [] - for item in body: - if item.get("type") == "message" and item.get("role") == "assistant": - for p in item.get("content", []): - if p.get("type") == "output_text": - assistant_msgs.append(p.get("text", "")[:300]) - - tool_summaries = [] - for item in body: - if item.get("type") in ("function_call", "function_call_output"): - tool_summaries.append(_item_summary(item, max_len=150)) - - files = _extract_files(body) - - summary_lines = [f"[Auto-compacted: {len(body)} earlier turns summarized to preserve context]"] - if user_queries: - summary_lines.append(f"User requests: {'; '.join(user_queries[-3:])}") - if assistant_msgs: - summary_lines.append(f"Assistant responses: {'; '.join(assistant_msgs[-3:])}") - if tool_summaries: - summary_lines.append(f"Actions taken ({len(tool_summaries)} steps):") - for ts in tool_summaries[-15:]: - summary_lines.append(f" {ts}") - if files: - summary_lines.append(f"Files touched: {', '.join(sorted(files)[-10:])}") - - summary_text = "\n".join(summary_lines) - summary_msg = { - "type": "message", - "role": "user", - "content": [{"type": "input_text", "text": summary_text}] - } - - print(f"[compact] {len(input_data)} items -> {len(head) + 1 + len(tail)} (compacted {len(body)} old items into summary)", file=sys.stderr) - return head + [summary_msg] + tail - -# ═══════════════════════════════════════════════════════════════════ -# Provider policies -# ═══════════════════════════════════════════════════════════════════ - -_PROVIDER_POLICIES = { - "crof": {"reasoning_mode": "off", "max_tokens": 32768, "strip_reasoning": True, - "tool_output_limit": 4000, "max_input_items": 18, "compaction": "aggressive", - "synthetic_tool_results": True}, - "chats-llm": {"reasoning_mode": "off", "max_tokens": 32768, "strip_reasoning": True, - "tool_output_limit": 4000, "max_input_items": 20, "compaction": "aggressive"}, - "z.ai": {"reasoning_mode": "medium", "max_tokens": 65536, "strip_reasoning": True, - "tool_output_limit": 8000, "max_input_items": 40, "compaction": "balanced"}, - "openrouter": {"reasoning_mode": "provider_default", "max_tokens": 32768, "strip_reasoning": True, - "tool_output_limit": 6000, "max_input_items": 35, "compaction": "balanced"}, - "openadapter": {"reasoning_mode": "off", "max_tokens": 32768, "strip_reasoning": True, - "tool_output_limit": 1000, "max_input_items": 10, "compaction": "aggressive", - "synthetic_tool_results": True}, - "cloudcode-pa": {"compaction": "aggressive", "context_size": 1000000, - "tool_output_limit": 6000, "max_input_items": 60}, - "googleapis": {"compaction": "balanced", "context_size": 1000000, - "tool_output_limit": 6000, "max_input_items": 80}, -} - -def provider_policy(target_url=None, backend=None): - host = urllib.parse.urlparse(target_url or TARGET_URL).netloc.lower() - for key, policy in _PROVIDER_POLICIES.items(): - if key in host: - return policy - return {} - -# ═══════════════════════════════════════════════════════════════════ -# Adaptive context compaction (model-aware) -# ═══════════════════════════════════════════════════════════════════ - -_MODEL_CONTEXT = { - "gpt-4o": 128000, "gpt-4o-mini": 128000, "gpt-5": 128000, - "claude-sonnet": 200000, "claude-haiku": 200000, - "glm-5.1": 128000, "glm-5": 128000, "glm-4": 128000, - "deepseek": 64000, "gemini-2.5-flash": 1000000, "gemini-2.5-pro": 2000000, - "gemini-3-flash": 1000000, "gemini-3.5-flash-low": 1000000, - "gemini-3.1-pro-low": 2000000, - "gemini-3.5-flash": 1000000, "gemini-3.1-pro": 2000000, - "Gemini 3.5 Flash": 1000000, "Gemini 3.1 Pro": 2000000, - "Claude Sonnet 4.6": 200000, "Claude Opus 4.6": 200000, - "GPT-OSS 120B": 128000, - "claude-sonnet-4-6": 200000, "claude-opus-4-6-thinking": 200000, - "gpt-oss-120b-medium": 128000, - "mimo": 32768, "minimax": 32768, "kimi": 128000, - "_default": 32768, -} - -def _context_limit_for_model(model): - if not model: - return _MODEL_CONTEXT["_default"] - ml = model.lower() - for key, limit in _MODEL_CONTEXT.items(): - if key != "_default" and key in ml: - return limit - return _MODEL_CONTEXT["_default"] - -def _estimate_tokens(obj): - if obj is None: - return 0 - if isinstance(obj, str): - return max(1, len(obj) // 4) - try: - raw = json.dumps(obj, ensure_ascii=False) - except Exception: - raw = str(obj) - return max(1, len(raw) // 4) - -def _adaptive_compact(input_data, model, policy=None): - policy = policy or {} - context_size = int(policy.get("context_size", _context_limit_for_model(model))) - input_budget = int(context_size * 0.80) - estimated = _estimate_tokens(input_data) - if estimated <= input_budget: - return input_data, False - if not isinstance(input_data, list): - return input_data, False - reduction = max(0.15, input_budget / max(estimated, 1)) - target_items = max(int(len(input_data) * reduction), 6) - if target_items >= len(input_data): - return input_data, False - head_end = 0 - for i, item in enumerate(input_data): - t = item.get("type") - if t == "message" and item.get("role") in ("developer", "system"): - head_end = i + 1 - elif t == "message" and item.get("role") == "user" and head_end == i: - head_end = i + 1 - else: - break - head = input_data[:head_end] - keep = max(4, target_items // 3) - tail_start = max(head_end, len(input_data) - keep) - while tail_start > head_end: - t = input_data[tail_start].get("type") - if t in ("function_call_output", "function_call"): - tail_start -= 1 - elif t == "message" and input_data[tail_start].get("role") == "assistant": - tail_start -= 1 - else: - break - tail = input_data[tail_start:] - body = input_data[head_end:tail_start] - if not body: - return head + tail, True - summary_lines = [f"[Auto-compacted: {len(body)} turns removed (budget={input_budget}tok, model={model})]"] - for item in body[-5:]: - summary_lines.append(_item_summary(item, max_len=120)) - summary_msg = {"type": "message", "role": "user", - "content": [{"type": "input_text", "text": "\n".join(summary_lines)}]} - print(f"[adaptive-compact] model={model} est={estimated}tok budget={input_budget}tok " - f"items {len(input_data)}->{len(head)+1+len(tail)}", file=sys.stderr) - return head + [summary_msg] + tail, True - -# ═══════════════════════════════════════════════════════════════════ -# Prompt Enhancer -# ═══════════════════════════════════════════════════════════════════ - -_PROMPT_ENHANCER_SYSTEM = """You are a prompt enhancement assistant for a coding agent (Codex CLI). -Your job: rewrite the user's latest message to be clearer, more specific, and more actionable. -Rules: -- Preserve the user's EXACT intent — never change what they want done -- Add explicit action verbs and step-by-step clarity -- If the message is vague ("fix it", "make it better"), infer context from prior conversation summary and make it specific -- Keep the enhanced prompt concise — no longer than 2x the original -- If the original prompt is already clear and specific, return it unchanged -- Output ONLY the enhanced prompt text, nothing else -- Never add tasks the user didn't ask for""" - -_PROMPT_ENHANCER_OFFLINE = """ - -You are a coding agent operating inside a context-compacted session. Follow these rules strictly: - -1. ACTION CLARITY: Re-read the user's latest message. Identify every explicit and implicit action request. Execute ALL of them — do not skip any. - -2. COMPACTED CONTEXT: Previous conversation was summarized. The summary preserves your task history but may lose details. If the user references earlier work ("fix that", "continue", "update it"), infer from the compacted summary what was done and what remains. - -3. NO CLARIFICATION ASKING: Never ask "which file?" or "what exactly?" — infer from context. If truly ambiguous, make a reasonable assumption and proceed. The user can correct you. - -4. DECISIVE EXECUTION: When the user says "fix", "update", "change", "add", "remove" — do it immediately in the relevant file(s). Do not describe what you would do — actually do it. - -5. COMPLETE EDITS: When editing files, make the FULL change requested. Do not partially apply edits or leave placeholders. - -6. PRESERVE WORKING STATE: Never break existing functionality. If changing code, keep all surrounding logic intact. - -7. MULTI-STEP REQUESTS: If the user asks for multiple things, do ALL of them in sequence. Do not stop after the first one. - - - -""" - -def _enhance_prompt_llm(text, compaction_summary=""): - global PROMPT_ENHANCER_MODEL, PROMPT_ENHANCER_URL, PROMPT_ENHANCER_KEY - if not PROMPT_ENHANCER_MODEL or not PROMPT_ENHANCER_URL: - return text - try: - messages = [ - {"role": "system", "content": _PROMPT_ENHANCER_SYSTEM}, - ] - if compaction_summary: - messages.append({"role": "user", "content": f"Context from earlier conversation (compacted):\n{compaction_summary[:2000]}"}) - messages.append({"role": "user", "content": f"Enhance this prompt:\n{text}"}) - body = json.dumps({"model": PROMPT_ENHANCER_MODEL, "messages": messages, "max_tokens": 2000, "temperature": 0.3}).encode() - headers = {"Content-Type": "application/json"} - if PROMPT_ENHANCER_KEY: - headers["Authorization"] = f"Bearer {PROMPT_ENHANCER_KEY}" - req = urllib.request.Request(f"{PROMPT_ENHANCER_URL.rstrip('/')}/chat/completions", data=body, headers=headers) - resp = urllib.request.urlopen(req, timeout=15) - data = json.loads(resp.read()) - enhanced = data.get("choices", [{}])[0].get("message", {}).get("content", "").strip() - if enhanced and len(enhanced) >= len(text) * 0.5: - print(f"[prompt-enhancer] AI enhanced: {text[:80]}... -> {enhanced[:80]}...", file=sys.stderr) - return enhanced - except Exception as e: - print(f"[prompt-enhancer] AI enhancement failed: {e}", file=sys.stderr) - return text - -def _apply_prompt_enhancer(input_data): - global PROMPT_ENHANCER_MODE - if not isinstance(input_data, list) or len(input_data) == 0: - return input_data - last_user_idx = None - for i in range(len(input_data) - 1, -1, -1): - item = input_data[i] - if isinstance(item, dict) and item.get("type") == "message" and item.get("role") == "user": - last_user_idx = i - break - if last_user_idx is None: - return input_data - item = input_data[last_user_idx] - content = item.get("content", "") - if isinstance(content, list): - text = content[0].get("text", "") if content else "" - elif isinstance(content, str): - text = content - else: - return input_data - if not text or len(text) < 5: - return input_data - if text.startswith(""): - return input_data - compaction_summary = "" - for it in input_data: - if isinstance(it, dict) and it.get("type") == "message" and it.get("role") == "user": - c = it.get("content", "") - t = "" - if isinstance(c, list): - t = c[0].get("text", "") if c else "" - elif isinstance(c, str): - t = c - if "[Auto-compacted:" in t: - compaction_summary = t[:3000] - break - if PROMPT_ENHANCER_MODE == "ai-powered" and PROMPT_ENHANCER_MODEL and PROMPT_ENHANCER_URL: - enhanced = _enhance_prompt_llm(text, compaction_summary) - else: - enhanced = text - enhanced = _PROMPT_ENHANCER_OFFLINE + enhanced - new_item = dict(item) - if isinstance(item.get("content"), list): - new_item["content"] = [{"type": "input_text", "text": enhanced}] - else: - new_item["content"] = enhanced - result = list(input_data) - result[last_user_idx] = new_item - print(f"[prompt-enhancer] mode={PROMPT_ENHANCER_MODE} enhanced last user message ({len(text)}->{len(enhanced)} chars)", file=sys.stderr) - return result - -# ═══════════════════════════════════════════════════════════════════ -# Tool-call pairing validator -# ═══════════════════════════════════════════════════════════════════ - -def validate_tool_pairs(input_items): - if not isinstance(input_items, list): - return [] - calls = {} - errors = [] - for idx, item in enumerate(input_items): - t = item.get("type") - if t == "function_call": - cid = item.get("call_id") or item.get("id") - if cid: - calls[cid] = idx - elif t == "function_call_output": - cid = item.get("call_id") or item.get("id") - if not cid or cid not in calls: - errors.append({"index": idx, "call_id": cid, "error": "orphan_function_call_output"}) - return errors - -def repair_orphan_tool_outputs(input_items, errors): - bad = {e["index"] for e in errors} - repaired = [] - for idx, item in enumerate(input_items): - if idx in bad: - output = item.get("output", "") - repaired.append({"type": "message", "role": "user", - "content": [{"type": "input_text", - "text": f"[Proxy: unmatched tool output]\n{str(output)[:4000]}"}]}) - else: - repaired.append(item) - return repaired - -def synthesize_tool_results_for_chat(input_items): - """Convert Responses function_call/function_call_output pairs into plain text. - - Some OpenAI-compatible providers accept tool calls on the first turn but fail - on the next request when role=tool messages are present. For those providers, - encode tool outputs as normal user text so the model can continue. - """ - if not isinstance(input_items, list): - return input_items, False - calls = {} - changed = False - out = [] - for item in input_items: - t = item.get("type") - if t == "function_call": - cid = item.get("call_id") or item.get("id") or "" - calls[cid] = item - changed = True - continue - if t == "function_call_output": - cid = item.get("call_id") or item.get("id") or "" - call = calls.get(cid, {}) - name = call.get("name", "tool") - args = call.get("arguments", "{}") - output = item.get("output", "") - text = ( - "Tool execution result. Continue the task using this result. " - "Do not repeat the same tool call unless more information is required.\n\n" - f"Tool: {name}\nArguments:\n```json\n{str(args)[:2000]}\n```\n" - f"Output:\n```\n{str(output)[:8000]}\n```" - ) - out.append({"type": "message", "role": "user", "content": [{"type": "input_text", "text": text}]}) - changed = True - continue - out.append(item) - return out, changed - -def has_function_call_output(input_items): - return isinstance(input_items, list) and any(i.get("type") == "function_call_output" for i in input_items) - -_TOOL_CALL_TEXT_PATTERNS = re.compile( - r'(?:^|\n)[\s•\-\*]*\(?' - r'(?:exec_command|write_to_file|exec_bash|bash|run_command|shell|edit_file|read_file|search_files|list_files)' - r'[\s:]', - re.I | re.MULTILINE -) - -def _text_looks_like_tool_calls(text): - if not text or len(text) < 6: - return False - return bool(_TOOL_CALL_TEXT_PATTERNS.search(text)) - -# ═══════════════════════════════════════════════════════════════════ -# Log redaction -# ═══════════════════════════════════════════════════════════════════ - -_SECRET_PATTERNS = [ - (r"sk-[A-Za-z0-9_\-]{20,}", "[REDACTED:key]"), - (r"sk-ant-[A-Za-z0-9_\-]{20,}", "[REDACTED:anthropic]"), - (r"gh[pousr]_[A-Za-z0-9_]{20,}", "[REDACTED:github]"), - (r"Bearer\s+[A-Za-z0-9._\-]{20,}", "Bearer [REDACTED]"), -] - -def _redact(text): - if not text: - return text - import re - for pattern, replacement in _SECRET_PATTERNS: - text = re.sub(pattern, replacement, text) - return text - -def _redact_json(obj): - try: - raw = json.dumps(obj, ensure_ascii=False) - except Exception: - raw = str(obj) - return _redact(raw) - -_MAX_SNAPSHOTS = 200 - -def save_request_snapshot(request_id, body): - if not request_id: - return request_id - snapshot = { - "_meta": { - "request_id": request_id, - "model": body.get("model", ""), - "stream": body.get("stream", False), - "ts": time.time(), - "ts_iso": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), - "status": "pending", - "duration_s": None, - "error": None, - }, - "request": json.loads(_redact_json(body)), - } - path = os.path.join(_REQUESTS_DIR, f"{request_id}.json") - tmp = path + ".tmp" - with open(tmp, "w", encoding="utf-8") as f: - json.dump(snapshot, f, ensure_ascii=False, indent=2) - os.replace(tmp, path) - _rotate_snapshots() - return request_id - -def update_snapshot_response(request_id, status, duration_s=None, error=None): - if not request_id: - return - path = os.path.join(_REQUESTS_DIR, f"{request_id}.json") - if not os.path.exists(path): - return - try: - with open(path) as f: - snapshot = json.load(f) - meta = snapshot.get("_meta", {}) - meta["status"] = status - if duration_s is not None: - meta["duration_s"] = round(duration_s, 3) - if error is not None: - meta["error"] = str(error)[:200] - snapshot["_meta"] = meta - tmp = path + ".tmp" - with open(tmp, "w", encoding="utf-8") as f: - json.dump(snapshot, f, ensure_ascii=False, indent=2) - os.replace(tmp, path) - except Exception: - pass - -def _rotate_snapshots(): - try: - files = sorted( - [os.path.join(_REQUESTS_DIR, f) for f in os.listdir(_REQUESTS_DIR) if f.endswith(".json")], - key=os.path.getmtime, - ) - while len(files) > _MAX_SNAPSHOTS: - os.remove(files.pop(0)) - except Exception: - pass - -# ═══════════════════════════════════════════════════════════════════ -# Rate-limit token buckets -# ═══════════════════════════════════════════════════════════════════ - -class TokenBucket: - def __init__(self, capacity=10, refill=1.0): - self.capacity = float(capacity) - self.tokens = float(capacity) - self.refill = float(refill) - self.updated = time.monotonic() - self.lock = threading.Lock() - def allow(self, cost=1): - with self.lock: - now = time.monotonic() - self.tokens = min(self.capacity, self.tokens + (now - self.updated) * self.refill) - self.updated = now - if self.tokens >= cost: - self.tokens -= cost - return True - return False - -_rate_buckets = {} -_rate_buckets_lock = threading.Lock() - -def _bucket_for_route(route): - name = route.get("name") or route.get("target_url") or "default" - with _rate_buckets_lock: - if name not in _rate_buckets: - _rate_buckets[name] = TokenBucket(capacity=10, refill=1.0) - return _rate_buckets[name] - -# ═══════════════════════════════════════════════════════════════════ -# OpenAI-compat backend -# ═══════════════════════════════════════════════════════════════════ - -def _inject_stored_reasoning(messages): - with _last_reasoning_lock: - snapshot = dict(_last_reasoning_store) - if not snapshot: - return messages - expired = [k for k, v in snapshot.items() if time.time() - v["ts"] > _RESPONSE_TTL] - for k in expired: - with _last_reasoning_lock: - _last_reasoning_store.pop(k, None) - snapshot.pop(k, None) - if not snapshot: - return messages - latest = max(snapshot.values(), key=lambda v: v["ts"]) - reasoning = latest.get("reasoning", "") - if not reasoning: - return messages - for msg in messages: - if msg.get("role") == "assistant" and "reasoning_content" not in msg and msg.get("tool_calls"): - msg["reasoning_content"] = reasoning - return messages - -def _normalize_tool_args(raw_args): - if not raw_args or raw_args == "{}": - return raw_args - try: - parsed = json.loads(raw_args) - if isinstance(parsed, dict): - if "Arguments" in parsed and "arguments" not in parsed: - inner = parsed["Arguments"] - if isinstance(inner, str): - inner = inner.strip() - for pfx in ("```json", "```"): - if inner.startswith(pfx): - inner = inner[len(pfx):].strip() - if inner.endswith("```"): - inner = inner[:-3].strip() - try: - inner_parsed = json.loads(inner) - if isinstance(inner_parsed, dict): - return json.dumps(inner_parsed) - except json.JSONDecodeError: - pass - if "cmd" not in parsed and "Arguments" in parsed: - inner = parsed["Arguments"] - if isinstance(inner, str): - inner = inner.strip() - for pfx in ("```json", "```"): - if inner.startswith(pfx): - inner = inner[len(pfx):].strip() - if inner.endswith("```"): - inner = inner[:-3].strip() - try: - inner_parsed = json.loads(inner) - if isinstance(inner_parsed, dict): - return json.dumps(inner_parsed) - except json.JSONDecodeError: - pass - return raw_args - except json.JSONDecodeError: - return raw_args - -_XML_TC_RE = re.compile(r'exec_command(.*?)', re.DOTALL) -_XML_ARG_VALUE_RE = re.compile(r'\s*') - -_PAREN_TC_RE = re.compile( - r'(?:^|[\n•\-\*]\s*)\(\s*(exec_command|write_to_file|exec_bash|bash|run_command|shell|edit_file|read_file|search_files|list_files)\b\s*(.*?)\)', - re.DOTALL | re.I -) - -def _extract_xml_tool_calls(text): - if not text: - return [] - results = [] - for m in _XML_TC_RE.finditer(text): - name = m.group(1) - rest = _XML_ARG_VALUE_RE.sub("", m.group(2)).strip() - args_str = "{}" - try: - for pfx in ("```json", "```"): - if rest.startswith(pfx): - rest = rest[len(pfx):].strip() - if rest.endswith("```"): - rest = rest[:-3].strip() - if rest.startswith("{"): - json.loads(rest) - args_str = rest - else: - json.loads(rest) - args_str = rest - except Exception: - if rest.startswith("{"): - args_str = rest - results.append({"name": name, "args": args_str, "call_id": f"xml_{len(results)}"}) - return results - -_NON_VISION_MODEL_PATTERNS = re.compile( - r'\b(deepseek|glm|mixtral|llama\b(?!.*vision)|command|dbrx|qwen\b(?!.*vl)|phi-?3(?!.*vision))', - re.I -) - -_vision_fail_cache = set() -_vision_fail_lock = threading.Lock() - -def _model_supports_vision(model): - if not model: - return True - with _vision_fail_lock: - if model in _vision_fail_cache: - return False - if _NON_VISION_MODEL_PATTERNS.search(model): - return False - return True - -def _mark_vision_fail(model): - if model: - with _vision_fail_lock: - _vision_fail_cache.add(model) - -def _strip_images_from_input(input_data, model): - if not isinstance(input_data, list) or _model_supports_vision(model): - return input_data - modified = False - result = [] - for item in input_data: - if item.get("type") != "message": - result.append(item) - continue - content = item.get("content", []) - if isinstance(content, str): - result.append(item) - continue - new_content = [] - has_img = False - for part in content: - if isinstance(part, str): - new_content.append(part) - continue - pt = part.get("type", "") - if pt in ("input_image", "image_url"): - if not has_img: - fname = part.get("image_url", {}).get("url", part.get("url", "image.png")) - if fname.startswith("data:"): - fname = "screenshot.png" - new_content.append({"type": "output_text", "text": f"[User attached image: {fname} — this model does not support vision]"}) - has_img = True - modified = True - else: - new_content.append(part) - if modified: - result.append({**item, "content": new_content}) - else: - result.append(item) - if modified: - print(f"[vision-filter] stripped {sum(1 for i in input_data if i.get('type')=='message' and any(c.get('type') in ('input_image','image_url') for c in (i.get('content') or []) if isinstance(c,dict)))} images for model={model}", file=sys.stderr) - return result - return input_data - -def oa_input_to_messages(input_data): - msgs = [] - tool_name_by_id = {} - if isinstance(input_data, str): - msgs.append({"role": "user", "content": input_data}) - elif isinstance(input_data, list): - pending_tool_calls = [] - last_flushed_ids = [] - for item in input_data: - t = item.get("type") - if t == "function_call": - tcid = item.get("call_id") or item.get("id") or uid("tc") - raw_args = item.get("arguments", "{}") - normalized_args = _normalize_tool_args(raw_args) - pending_tool_calls.append( - {"id": tcid, - "type": "function", - "function": {"name": item.get("name", ""), - "arguments": normalized_args}}) - tool_name_by_id[tcid] = item.get("name", "") - continue - if pending_tool_calls: - last_flushed_ids = [tc["id"] for tc in pending_tool_calls] - msgs.append({"role": "assistant", "content": None, "tool_calls": pending_tool_calls}) - pending_tool_calls = [] - if t == "message": - role = item.get("role", "user") - if role == "developer": - role = "system" - text = "" - reasoning_text = "" - content = item.get("content", []) - if isinstance(content, str): - text = content - else: - for part in content: - if isinstance(part, str): - text += part - continue - pt = part.get("type", "") - if pt in ("input_text", "output_text"): - text += part.get("text", "") - elif pt in ("reasoning",): - for rp in part.get("content", []): - reasoning_text += rp.get("text", "") - elif pt == "input_image": - img = part.get("image_url", part) - msgs.append({"role": role, "content": [{"type": "text", "text": text}, - {"type": "image_url", "image_url": img}]}) - text = None - break - if text is not None: - msg = {"role": role, "content": text} - if reasoning_text and role == "assistant": - msg["reasoning_content"] = reasoning_text - msgs.append(msg) - elif t == "function_call_output": - tcid = item.get("call_id") or item.get("id") or "" - if not tcid and last_flushed_ids: - idx = len([m for m in msgs if m.get("role") == "tool"]) - if idx < len(last_flushed_ids): - tcid = last_flushed_ids[idx] - msgs.append({"role": "tool", "tool_call_id": tcid, - "tool_name": tool_name_by_id.get(tcid, ""), - "content": item.get("output", "")}) - if pending_tool_calls: - msgs.append({"role": "assistant", "content": None, "tool_calls": pending_tool_calls}) - return msgs - -def cc_input_to_messages(input_data, instructions="", schema=None): - """Convert Responses API input into CommandCode /alpha/generate messages. - - [FIX 1] All messages use STRING content (not content blocks). - CC API rejects params.messages[i].content when it's an array. - Tool results are role="user" with plain text content. - Tool calls: inline JSON text in assistant messages (e.g. {"type":"tool-call","id":"..."}). - - The model echoes this format back in its response text-delta events. - _parse_commandcode_text_tool_calls extracts them via _extract_raw_json_tool_calls. - - Schema parameter is accepted but not used for format decisions — - the conservative string-content format is always used regardless of schema hints. - """ - msgs = [] - pending_tool_calls = [] - last_flushed_ids = [] - - def text_from_content(content): - if isinstance(content, str): - return content - text = "" - for part in content or []: - if isinstance(part, str): - text += part - continue - if not isinstance(part, dict): - continue - if part.get("type") in ("input_text", "output_text", "text"): - text += part.get("text", "") - return text - - def flush_tool_calls(): - nonlocal pending_tool_calls, last_flushed_ids - if not pending_tool_calls: - return - last_flushed_ids = [tc["id"] for tc in pending_tool_calls] - # Tool calls as plain text in assistant message - tc_text = "\n".join( - json.dumps(tc, ensure_ascii=False) for tc in pending_tool_calls - ) - msgs.append({"role": "assistant", "content": tc_text}) - pending_tool_calls = [] - - if instructions: - msgs.append({"role": "user", "content": instructions}) - - if isinstance(input_data, str): - msgs.append({"role": "user", "content": input_data}) - return msgs - if not isinstance(input_data, list): - return msgs - - for item in input_data: - if not isinstance(item, dict): - continue - t = item.get("type") - if t == "function_call": - tcid = item.get("call_id") or item.get("id") or uid("call") - name = item.get("name") or "exec_command" - pending_tool_calls.append({ - "type": "tool-call", - "id": tcid, - "name": name, - "arguments": item.get("arguments") or "{}", - }) - continue - flush_tool_calls() - if t == "message": - role = item.get("role", "user") - if role not in ("user", "assistant"): - role = "user" - text = text_from_content(item.get("content", [])) - msgs.append({"role": role, "content": text}) - elif t == "function_call_output": - output = item.get("output", "") - if not isinstance(output, str): - output = json.dumps(output, ensure_ascii=False) - # /alpha/generate expects string content for ALL messages - msgs.append({"role": "user", "content": output[:8000]}) - flush_tool_calls() - return msgs - -def oa_convert_tools(tools, strict=False): - if not tools: - return None - out = [] - for t in tools: - if t.get("type") != "function": - continue - fn = t.get("function", {}) - name = "" - if fn: - name = (fn.get("name") or "").strip() - else: - 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": 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): - choice = chat_resp["choices"][0] - msg = choice["message"] - content = msg.get("content") or "" - finish = choice.get("finish_reason", "stop") - fm = {"stop": "completed", "length": "incomplete", "tool_calls": "completed", "content_filter": "incomplete"} - status = fm.get(finish, "incomplete") - outputs = [] - if content: - outputs.append({"type": "message", "id": uid("msg"), "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": content, "annotations": []}]}) - for tc in msg.get("tool_calls") or []: - fn = tc.get("function", {}) - outputs.append({"type": "function_call", "id": uid("fc"), "call_id": tc.get("id"), - "name": fn.get("name"), "arguments": fn.get("arguments", "{}"), "status": "completed"}) - usage = chat_resp.get("usage", {}) - return {"id": resp_id or uid("resp"), "object": "response", "created": int(time.time()), - "model": model, "status": status, "output": outputs, - "usage": {"input_tokens": usage.get("prompt_tokens", 0), - "output_tokens": usage.get("completion_tokens", 0), - "total_tokens": usage.get("total_tokens", 0), - "input_tokens_details": {"cached_tokens": usage.get("prompt_tokens_details", {}).get("cached_tokens", 0)}}} - -def oa_stream_to_sse(chat_stream, model, req_id, _reasoning_out=None): - resp_id = req_id or uid("resp") - msg_id = uid("msg") - text_buf = "" - reasoning_buf = "" - reasoning_opened = False - tc_buf = {} - fr = None - msg_opened = False - - yield emit("response.created", {"type": "response.created", - "response": {"id": resp_id, "object": "response", "model": model, - "status": "in_progress", "created": int(time.time()), "output": []}}) - yield emit("response.in_progress", {"type": "response.in_progress", "response": {"id": resp_id}}) - - 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 - if not line.startswith("data: "): - continue - try: - chunk = json.loads(line[6:]) - except json.JSONDecodeError: - continue - choices = chunk.get("choices", []) - if not choices: - continue - delta = choices[0].get("delta", {}) - fr = choices[0].get("finish_reason") - - rc = delta.get("reasoning_content") or delta.get("reasoning") - if rc: - if not reasoning_opened: - reasoning_opened = True - reasoning_buf += rc - yield emit("response.reasoning.delta", {"type": "response.reasoning.delta", "delta": rc}) - - content = delta.get("content") - if content: - if not msg_opened: - msg_id = uid("msg") - yield emit("response.output_item.added", {"type": "response.output_item.added", - "item": {"type": "message", "id": msg_id, "role": "assistant", "status": "in_progress", "content": []}}) - yield emit("response.content_part.added", {"type": "response.content_part.added", - "part": {"type": "output_text", "text": "", "annotations": []}, "item_id": msg_id}) - msg_opened = True - text_buf += content - yield emit("response.output_text.delta", {"type": "response.output_text.delta", - "delta": content, "item_id": msg_id, "content_index": 0}) - - for tc in delta.get("tool_calls") or []: - idx = tc.get("index", 0) - if idx not in tc_buf: - fid = uid("fc") - tc_buf[idx] = {"id": fid, "call_id": tc.get("id", fid), "name": "", "args": ""} - yield emit("response.output_item.added", {"type": "response.output_item.added", - "item": {"type": "function_call", "id": fid, "call_id": tc_buf[idx]["call_id"], - "name": "", "arguments": "", "status": "in_progress"}}) - fn = tc.get("function", {}) - if "name" in fn and fn["name"]: - tc_buf[idx]["name"] = fn["name"] - if "arguments" in fn and fn["arguments"]: - tc_buf[idx]["args"] += fn["arguments"] - yield emit("response.output_text.delta", {"type": "response.function_call_arguments.delta", - "delta": fn["arguments"], "item_id": tc_buf[idx]["id"]}) - - reasoning_rsn_id = uid("rsn") if reasoning_buf else None - if reasoning_opened: - yield emit("response.reasoning.done", {"type": "response.reasoning.done", - "item_id": reasoning_rsn_id, "text": reasoning_buf}) - - if msg_opened: - yield emit("response.output_text.done", {"type": "response.output_text.done", - "text": text_buf, "item_id": msg_id, "content_index": 0}) - yield emit("response.content_part.done", {"type": "response.content_part.done", - "part": {"type": "output_text", "text": text_buf, "annotations": []}, "item_id": msg_id}) - yield emit("response.output_item.done", {"type": "response.output_item.done", - "item": {"type": "message", "id": msg_id, "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": text_buf, "annotations": []}]}}) - - for idx in sorted(tc_buf): - t = tc_buf[idx] - yield emit("response.function_call_arguments.done", {"type": "response.function_call_arguments.done", - "item_id": t["id"], "name": t["name"], "arguments": t["args"]}) - yield emit("response.output_item.done", {"type": "response.output_item.done", - "item": {"type": "function_call", "id": t["id"], "call_id": t["call_id"], - "name": t["name"], "arguments": t["args"], "status": "completed"}}) - - fm = {"stop": "completed", "length": "incomplete", "tool_calls": "completed", "content_filter": "incomplete"} - status = fm.get(fr, "incomplete") - final_out = [] - if reasoning_buf: - final_out.append({"type": "reasoning", "id": reasoning_rsn_id, "status": "completed", - "content": [{"type": "text", "text": reasoning_buf}]}) - if msg_opened: - msg_content = [] - if reasoning_buf: - msg_content.append({"type": "output_text", "text": text_buf, "annotations": []}) - else: - msg_content.append({"type": "output_text", "text": text_buf, "annotations": []}) - final_out.append({"type": "message", "id": msg_id, "role": "assistant", "status": "completed", - "content": msg_content}) - for idx in sorted(tc_buf): - t = tc_buf[idx] - final_out.append({"type": "function_call", "id": t["id"], "call_id": t["call_id"], - "name": t["name"], "arguments": t["args"], "status": "completed"}) - yield emit("response.completed", {"type": "response.completed", - "response": {"id": resp_id, "object": "response", "model": model, - "status": status, "created": int(time.time()), "output": final_out}}) - if _reasoning_out is not None: - _reasoning_out["text"] = reasoning_buf - _reasoning_out["tool_calls"] = [tc_buf[i] for i in sorted(tc_buf)] if tc_buf else [] - -# ═══════════════════════════════════════════════════════════════════ -# Anthropic backend -# ═══════════════════════════════════════════════════════════════════ - -def an_input_to_messages(input_data): - msgs = [] - if isinstance(input_data, str): - msgs.append({"role": "user", "content": input_data}) - elif isinstance(input_data, list): - for item in input_data: - t = item.get("type") - if t == "message": - role = item.get("role", "user") - if role == "developer": - role = "user" - text = "" - thinking_blocks = [] - for part in item.get("content", []): - pt = part.get("type", "") - if pt in ("input_text", "output_text"): - text += part.get("text", "") - elif pt in ("reasoning", "thinking"): - thinking_text = "" - for rp in part.get("content", []): - thinking_text += rp.get("text", "") - if thinking_text: - thinking_blocks.append({"type": "thinking", "thinking": thinking_text, "signature": part.get("signature", "")}) - if role == "assistant": - content_parts = [] - if thinking_blocks: - content_parts.extend(thinking_blocks) - if text: - content_parts.append({"type": "text", "text": text}) - msgs.append({"role": "assistant", "content": content_parts if content_parts else text}) - else: - msgs.append({"role": "user", "content": text}) - elif t == "function_call": - msgs.append({"role": "assistant", "content": [ - {"type": "tool_use", "id": item.get("call_id", item.get("id", uid("tu"))), - "name": item.get("name", ""), - "input": json.loads(item.get("arguments", "{}"))} - ]}) - elif t == "function_call_output": - msgs.append({"role": "user", "content": [ - {"type": "tool_result", "tool_use_id": item.get("id", ""), - "content": item.get("output", "")} - ]}) - return msgs - -def an_convert_tools(tools): - if not tools: - return None - out = [] - for t in tools: - if t.get("type") != "function": - continue - fn = t.get("function", {}) - if fn: - out.append({"name": fn.get("name"), "description": fn.get("description", ""), - "input_schema": fn.get("parameters", {"type": "object", "properties": {}})}) - else: - out.append({"name": t.get("name"), "description": t.get("description", ""), - "input_schema": t.get("parameters", {"type": "object", "properties": {}})}) - return out or None - -def an_resp_to_responses(anthro_resp, model, resp_id=None): - blocks = anthro_resp.get("content", []) - sr = anthro_resp.get("stop_reason", "end_turn") - sm = {"end_turn": "completed", "max_tokens": "incomplete", "stop_sequence": "completed", "tool_use": "completed"} - status = sm.get(sr, "incomplete") - outputs = [] - for b in blocks: - bt = b.get("type", "") - if bt == "text": - outputs.append({"type": "message", "id": uid("msg"), "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": b.get("text", ""), "annotations": []}]}) - elif bt == "tool_use": - outputs.append({"type": "function_call", "id": uid("fc"), "call_id": b.get("id", ""), - "name": b.get("name", ""), "arguments": json.dumps(b.get("input", {})), - "status": "completed"}) - elif bt == "thinking": - outputs.append({"type": "reasoning", "id": uid("rsn"), "status": "completed", - "content": [{"type": "text", "text": b.get("thinking", "")}]}) - usage = anthro_resp.get("usage", {}) - return {"id": resp_id or uid("resp"), "object": "response", "created": int(time.time()), - "model": model, "status": status, "output": outputs, - "usage": {"input_tokens": usage.get("input_tokens", 0), - "output_tokens": usage.get("output_tokens", 0), - "total_tokens": usage.get("input_tokens", 0) + usage.get("output_tokens", 0), - "input_tokens_details": {"cached_tokens": 0}}} - -def an_stream_to_sse(stream, model, req_id): - resp_id = req_id or uid("resp") - completed = [] - msg_id = uid("msg") - text_buf = "" - tc_id = None - tc_call_id = None - tc_name = "" - tc_args = "" - block_type = None - stop_reason = "end_turn" - - yield emit("response.created", {"type": "response.created", - "response": {"id": resp_id, "object": "response", "model": model, - "status": "in_progress", "created": int(time.time()), "output": []}}) - yield emit("response.in_progress", {"type": "response.in_progress", "response": {"id": resp_id}}) - - for raw in stream: - line = raw.decode("utf-8", errors="replace").strip() - if not line: - continue - if line.startswith("event: "): - evt_type = line[7:] - continue - if not line.startswith("data: "): - continue - try: - data = json.loads(line[6:]) - except json.JSONDecodeError: - continue - - et = data.get("type", "") - - if et == "message_start": - pass - - elif et == "content_block_start": - cb_type = data.get("content_block", {}).get("type", "") - block_type = cb_type - if cb_type == "text": - msg_id = uid("msg") - yield emit("response.output_item.added", {"type": "response.output_item.added", - "item": {"type": "message", "id": msg_id, "role": "assistant", - "status": "in_progress", "content": []}}) - yield emit("response.content_part.added", {"type": "response.content_part.added", - "part": {"type": "output_text", "text": "", "annotations": []}, "item_id": msg_id}) - elif cb_type == "tool_use": - cb = data.get("content_block", {}) - tc_id = uid("fc") - tc_call_id = cb.get("id", tc_id) - tc_name = cb.get("name", "") - yield emit("response.output_item.added", {"type": "response.output_item.added", - "item": {"type": "function_call", "id": tc_id, "call_id": tc_call_id, - "name": tc_name, "arguments": "", "status": "in_progress"}}) - elif cb_type == "thinking": - pass - - elif et == "content_block_delta": - dd = data.get("delta", {}) - dt = dd.get("type", "") - if dt == "text_delta": - txt = dd.get("text", "") - text_buf += txt - yield emit("response.output_text.delta", {"type": "response.output_text.delta", - "delta": txt, "item_id": msg_id, "content_index": 0}) - elif dt == "input_json_delta": - pj = dd.get("partial_json", "") - tc_args += pj - yield emit("response.output_text.delta", {"type": "response.function_call_arguments.delta", - "delta": pj, "item_id": tc_id}) - elif dt == "thinking_delta": - tk = dd.get("thinking", "") - yield emit("response.reasoning.delta", {"type": "response.reasoning.delta", "delta": tk}) - - elif et == "content_block_stop": - if block_type == "text": - yield emit("response.output_text.done", {"type": "response.output_text.done", - "text": text_buf, "item_id": msg_id, "content_index": 0}) - yield emit("response.content_part.done", {"type": "response.content_part.done", - "part": {"type": "output_text", "text": text_buf, "annotations": []}, "item_id": msg_id}) - yield emit("response.output_item.done", {"type": "response.output_item.done", - "item": {"type": "message", "id": msg_id, "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": text_buf, "annotations": []}]}}) - completed.append({"type": "message", "id": msg_id, "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": text_buf, "annotations": []}]}) - text_buf = "" - elif block_type == "tool_use": - yield emit("response.function_call_arguments.done", {"type": "response.function_call_arguments.done", - "item_id": tc_id, "name": tc_name, "arguments": tc_args}) - yield emit("response.output_item.done", {"type": "response.output_item.done", - "item": {"type": "function_call", "id": tc_id, "call_id": tc_call_id, - "name": tc_name, "arguments": tc_args, "status": "completed"}}) - completed.append({"type": "function_call", "id": tc_id, "call_id": tc_call_id, - "name": tc_name, "arguments": tc_args, "status": "completed"}) - tc_id = None - tc_args = "" - block_type = None - - elif et == "message_delta": - stop_reason = data.get("delta", {}).get("stop_reason", "end_turn") - - elif et == "message_stop": - sm = {"end_turn": "completed", "max_tokens": "incomplete", - "stop_sequence": "completed", "tool_use": "completed"} - status = sm.get(stop_reason, "incomplete") - yield emit("response.completed", {"type": "response.completed", - "response": {"id": resp_id, "object": "response", "model": model, - "status": status, "created": int(time.time()), "output": completed}}) - -_DEFAULT_CC_CONFIG = { - "workingDir": tempfile.gettempdir(), - "date": "", - "environment": "windows" if _IS_WINDOWS else "linux", - "shell": "powershell" if _IS_WINDOWS else "bash", - "files": [], - "structure": [], - "isGitRepo": False, - "currentBranch": "", - "mainBranch": "", - "gitStatus": "", - "recentCommits": [], -} - -def _cc_config(): - cfg = dict(_DEFAULT_CC_CONFIG) - cfg["date"] = time.strftime("%Y-%m-%d") - return cfg - -def cc_convert_tools(tools): - return oa_convert_tools(tools) - -def _strip_xmlish_tags(text): - return re.sub(r"<[^>]+>", "", text or "") - -def _unwrap_cmd(cmd_val): - """[FIX 11] Self-healing: unwrap double-wrapped cmd values. - - Model sometimes generates: {"cmd": "{\"cmd\": \"actual_command\"}"} - Detect when cmd value is itself a JSON object with a nested "cmd" key, - and extract the real command string. Recursively unwraps up to 3 levels. - """ - if not isinstance(cmd_val, str) or not cmd_val.startswith("{"): - return cmd_val - for _ in range(3): - try: - inner = json.loads(cmd_val) - if isinstance(inner, dict) and "cmd" in inner and isinstance(inner["cmd"], str): - cmd_val = inner["cmd"] - else: - break - except Exception: - break - return cmd_val - -def _build_explore_cmd(text_for_url): - """Module-level explore command builder. Extracts repo URL from text, - builds a curl pipeline to fetch README, contents listing, and releases. - Used by _parse_commandcode_text_tool_calls (closure wrapper) and - cc_stream_to_sse (stuck recovery heuristic).""" - if not text_for_url: - return None, None - url_m = re.search(r"https?://[^\s\]'\\>\",]+", text_for_url) - repo_url = url_m.group(0).rstrip(")].,;'\\\"") if url_m else "" - if not repo_url and isinstance(text_for_url, str): - try: - _parsed = json.loads(text_for_url) - if isinstance(_parsed, list): - for _item in _parsed: - _c = _item.get("content", "") if isinstance(_item, dict) else str(_item) - url_m2 = re.search(r"https?://[^\s\]'\\>\",]+", _c) - if url_m2: - repo_url = url_m2.group(0).rstrip(")].,;'\\\"") - break - except Exception: - pass - if not repo_url: - return None, None - if repo_url.endswith(".git"): - repo_url = repo_url[:-4] - if "/api/v1/repos/" not in repo_url: - host_m = re.match(r"(https?://[^/]+)/(.*)", repo_url) - if host_m: - host, path = host_m.groups() - api_base = f"{host}/api/v1/repos/{path}" - else: - api_base = repo_url.replace("/admin/", "/api/v1/repos/") - else: - api_base = repo_url - if _IS_WINDOWS: - cmd = ( - f"cd $env:TEMP; " - f"$r = Invoke-WebRequest -Uri '{api_base}/contents/README.md' -UseBasicParsing -TimeoutSec 15 2>$null; " - f"if ($r) {{ $j = $r.Content | ConvertFrom-Json; [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($j.content)) | Select-Object -First 600 }}; " - f"$r2 = Invoke-WebRequest -Uri '{api_base}/contents' -UseBasicParsing -TimeoutSec 15 2>$null; " - f"if ($r2) {{ $j2 = $r2.Content | ConvertFrom-Json; $j2 | Select-Object -First 50 | ForEach-Object {{ $_.path + ' ' + $_.type }} }}; " - f"$r3 = Invoke-WebRequest -Uri '{api_base}/releases' -UseBasicParsing -TimeoutSec 15 2>$null; " - f"if ($r3) {{ ($r3.Content | ConvertFrom-Json | Select-Object -First 3 | ConvertTo-Json).Substring(0, [Math]::Min(2000, ($r3.Content | ConvertFrom-Json | Select-Object -First 3 | ConvertTo-Json).Length)) }}" - ) - else: - cmd = ( - f"cd /tmp && " - f"curl -sL --max-time 15 '{api_base}/contents/README.md' 2>/dev/null | " - f"python3 -c \"import sys,json,base64; d=json.load(sys.stdin); print(base64.b64decode(d['content']).decode())\" 2>/dev/null | head -600 && " - f"curl -sL --max-time 15 '{api_base}/contents' 2>/dev/null | python3 -c \"import sys,json; d=json.load(sys.stdin); print('\\n'.join(f'{{x.get(\'path\')}} {{x.get(\'type\')}}' for x in d[:50]))\" 2>/dev/null && " - f"curl -sL --max-time 15 '{api_base}/releases' 2>/dev/null | python3 -c \"import sys,json; d=json.load(sys.stdin); print(json.dumps(d[:3], indent=2)[:2000])\" 2>/dev/null" - ) - return cmd, "Explore repository to understand the app and gather README, root contents, and releases for the landing page." - -def _parse_commandcode_text_tool_calls(text): - """Parse CommandCode's text-form tool calls into Responses function calls. - - Handles THREE formats: - 1. XML: ``...`` (original) - 2. Function: ``...`` (original) - 3. [FIX 5] Raw JSON inline: {"type":"tool-call","id":"...","name":"exec_command","arguments":"{...}"} - - Format 3 exists because cc_input_to_messages sends tool calls as inline JSON text. - The CC model echoes this format back in its response. - Extraction is done by _extract_raw_json_tool_calls() which is appended after the - XML pattern loop. See that function for details on malformed-JSON handling. - - Tolerant of: unescaped inner quotes, unbalanced braces, missing type/id fields, - sandbox_permissions at top level vs nested inside arguments, etc. - """ - calls = [] - if not text: - return calls - - _build_explore_cmd_local = _build_explore_cmd - - # [FIX 17] DSML tool_call blocks used by the model now. - # Example: - # <||DSML||tool_calls> - # <||DSML||invoke name="exec"> - # <||DSML||parameter name="command" string="true">curl ... - # <||DSML||parameter name="sandbox_permissions" string="true">require_escalated - # <||DSML||parameter name="justification" string="true">... - # <||DSML||parameter name="prefix_rule" string="true">["/bin/bash", "-lc", "curl ..."] - # - # - for m in re.finditer(r"<[^>]*tool_calls[^>]*>(.*?)]*tool_calls[^>]*>", text, re.DOTALL | re.IGNORECASE): - block = m.group(1) or "" - for im in re.finditer(r"<[^>]*invoke[^>]*name=\"([^\"]+)\"[^>]*>(.*?)]*invoke>", block, re.DOTALL | re.IGNORECASE): - raw_name = (im.group(1) or "").strip() - body = (im.group(2) or "").strip() - if not body: - continue - cmd = None - sandbox_permissions = None - justification = None - # Parameter tags are the canonical source. - for pm in re.finditer(r"<[^>]*parameter[^>]*name=\"([^\"]+)\"[^>]*>(.*?)]*parameter>", body, re.DOTALL | re.IGNORECASE): - key = (pm.group(1) or "").strip().lower() - val = _strip_xmlish_tags(pm.group(2)).strip() - # [FIX 21] Accept both "command" and "cmd" parameter names. - # The tool schema defines the parameter as "cmd" (see exec_command schema), - # but the model sometimes uses "command" (especially from prefix_rule fallback). - # Previously only "command" was accepted, so DSML blocks with name="cmd" - # were silently dropped — causing Codex CLI to stop mid-task. - if key in ("command", "cmd"): - cmd = val - elif key == "prefix_rule" and not cmd: - try: - pr_obj = json.loads(val) - except Exception: - pr_obj = None - if isinstance(pr_obj, list) and pr_obj and isinstance(pr_obj[-1], str): - cmd = pr_obj[-1] - elif key == "sandbox_permissions": - sandbox_permissions = val - elif key == "justification": - justification = val - - # [FIX 20] Support explore / explore_agent in DSML blocks - is_explore = raw_name.lower() in ("explore", "explore_agent") - if is_explore: - explore_cmd, explore_just = _build_explore_cmd_local(body) - if explore_cmd: - cmd = explore_cmd - justification = explore_just - - # Fallback: if the body contains a raw JSON command. - if not cmd: - jm = re.search(r'"(?:command|cmd)"\s*:\s*"((?:[^"\\]|\\.)*)"', body, re.DOTALL) - if jm: - cmd = jm.group(1).replace('\\n', '\n').replace('\\"', '"').strip() - if not cmd: - continue - # [FIX 19] Translate execute_request and other variations to exec_command (CLI only supports exec_command) - # [FIX 20] Translate explore and explore_agent to exec_command - tool_name = "exec_command" if raw_name.lower() in ("exec", "bash", "shell", "terminal", "run_command", "execute_request", "execute_command", "run_shell_command", "run_shell", "run", "explore", "explore_agent") else raw_name - args = {"cmd": _unwrap_cmd(cmd)} - if sandbox_permissions: - args["sandbox_permissions"] = sandbox_permissions if sandbox_permissions in ("use_default", "require_escalated", "with_user_approval") else "require_escalated" - if justification: - args["justification"] = justification - calls.append({ - "full_match": m.group(0), - "name": tool_name, - "arguments": json.dumps(args, ensure_ascii=False), - }) - - # [FIX 16] Native blocks from CommandCode. - # Example: - # - # sandbox_permissions: require_escalated - # justification: ... - # prefix_rule: ["/bin/bash", "-lc", "curl ..."] - # - # Convert into exec_command calls by extracting the command from prefix_rule. - for m in re.finditer(r"(.*?)", text, re.DOTALL | re.IGNORECASE): - body = (m.group(1) or "").strip() - if not body: - continue - sandbox_permissions = None - justification = None - cmd = None - # Try line-oriented parsing first. - for line in body.splitlines(): - s = line.strip() - if s.lower().startswith("sandbox_permissions:"): - sandbox_permissions = s.split(":", 1)[1].strip() - elif s.lower().startswith("justification:"): - justification = s.split(":", 1)[1].strip() - elif s.lower().startswith("prefix_rule:"): - pr = s.split(":", 1)[1].strip() - try: - pr_obj = json.loads(pr) - except Exception: - pr_obj = None - if isinstance(pr_obj, list) and pr_obj: - # If the last arg exists, it is typically the shell command. - cmd = pr_obj[-1] if isinstance(pr_obj[-1], str) else None - elif pr.startswith("[") and pr.endswith("]"): - parts = re.findall(r'"((?:[^"\\]|\\.)*)"', pr) - if parts: - cmd = parts[-1].encode().decode("unicode_escape") - # Fallback: grab a shell-looking line if prefix_rule wasn't parseable. - if not cmd: - for line in body.splitlines(): - s = line.strip() - if re.match(r"^(curl|wget|python3?|node|npm|pnpm|yarn|cat|ls|find|grep|rg|sed|awk|git|mkdir|touch|printf|echo)\b", s): - cmd = s - break - if not cmd: - continue - args = {"cmd": cmd} - if sandbox_permissions: - args["sandbox_permissions"] = sandbox_permissions if sandbox_permissions in ("use_default", "require_escalated", "with_user_approval") else "require_escalated" - if justification: - args["justification"] = justification - calls.append({ - "full_match": m.group(0), - "name": "exec_command", - "arguments": json.dumps(args, ensure_ascii=False), - }) - - # [FIX 15] Native blocks from CommandCode. - # Format seen in logs: - # \nmessages: [{...}]\n - # Treat as an assistant-requested agent call so the loop can continue. - for m in re.finditer(r"(.*?)|\s*messages:\s*(\[.*?\])", text, re.DOTALL | re.IGNORECASE): - body = m.group(1) or m.group(2) or "" - body = body.strip() - msgs = None - if body: - try: - msgs = json.loads(body) if body.startswith("[") else None - except Exception: - msgs = None - if msgs is None and body: - mm = re.search(r"(\[.*\])", body, re.DOTALL) - if mm: - try: - msgs = json.loads(mm.group(1)) - except Exception: - msgs = None - if msgs is None: - msgs = body - text_for_url = body if isinstance(body, str) else json.dumps(body, ensure_ascii=False) - cmd, justification = _build_explore_cmd_local(text_for_url) - if not cmd: - cmd = "echo 'explore_agent: unable to extract repository URL'" - justification = "Fallback for explore_agent block without URL." - args = {"cmd": cmd} - if justification: - args["justification"] = justification - calls.append({ - "full_match": m.group(0), - "name": "exec_command", - "arguments": json.dumps(args, ensure_ascii=False), - }) - - if not calls and text.count("") >= 2: - url_m = re.search(r"https?://[^\s\]'\\>\"]+", text) - if not url_m: - for prev_url in _last_user_urls: - url_m = re.search(r"https?://[^\s\]'\\>\"]+", prev_url) - if url_m: - break - if url_m: - explore_url = url_m.group(0).rstrip(")].,;'\\") - cmd, justification = _build_explore_cmd_local(explore_url) - if cmd: - calls.append({ - "full_match": "...", - "name": "exec_command", - "arguments": json.dumps({"cmd": cmd, "justification": justification or "Explore repository"}, ensure_ascii=False), - }) - - # [FIX 24] Handle and blocks. - # The model produces these when it wants elevated permissions but the CC - # adapter doesn't support them. Synthesize a proceed command so the loop continues. - if not calls: - for m in re.finditer(r"<(?:require_escalation|request_escalation_permission)>(.*?)", text, re.DOTALL | re.IGNORECASE): - body_escal = (m.group(1) or "").strip() - _inner_url_m = re.search(r"https?://[^\s\]'\\>\",]+", body_escal) - if _inner_url_m: - _e_url = _inner_url_m.group(0).rstrip(")].,;'\\\"") - _e_cmd, _e_just = _build_explore_cmd_local(_e_url) - if _e_cmd: - calls.append({ - "full_match": m.group(0), - "name": "exec_command", - "arguments": json.dumps({"cmd": _e_cmd, "justification": _e_just or "Escalation block with URL — auto-proceed"}, ensure_ascii=False), - }) - continue - if not calls: - calls.append({ - "full_match": m.group(0), - "name": "exec_command", - "arguments": json.dumps({"cmd": "echo 'escalation: auto-proceeding — no specific command in escalation block'", "justification": "Auto-proceed past escalation request"}, ensure_ascii=False), - }) - - # [FIX 24b] Bare or - # without closing tags. Just auto-proceed. - if not calls and re.search(r"<(?:require_escalation|request_escalation_permission)[\s/>]", text, re.IGNORECASE): - calls.append({ - "full_match": "", - "name": "exec_command", - "arguments": json.dumps({"cmd": "echo 'escalation: auto-proceeding past bare escalation tag'", "justification": "Auto-proceed past bare escalation tag"}, ensure_ascii=False), - }) - - patterns = [ - r"\s]+)['\"]?)?>(.*?)", - r"(.*?)", - # [FIX 14] CC model actual output: \n{"command":"...", "description":"..."} - # No \s*(\{.*?\})(?:\s*= len(text) or text[start] != '{': - return -1 - depth = 0 - i = start - in_str = False - escape = False - while i < len(text): - ch = text[i] - if escape: - escape = False - elif ch == '\\': - escape = True - elif ch == '"': - in_str = not in_str - elif not in_str: - if ch == '{': - depth += 1 - elif ch == '}': - depth -= 1 - if depth == 0: - return i - i += 1 - return -1 - - def _extract_field(text, key, end_chars=',}'): - """Extract a field value after "key": in rough JSON text. - - [FIX 7] Handles values starting with \" (backslash-quote) which occurs when - the model generates properly-escaped JSON inside a string value. - Without this fix, _extract_field returns None for escaped values, - causing sandbox_permissions/justification to not be extracted from - the parsed args dict (falling through to raw snippet extraction). - - Also tolerant of unescaped quotes inside string values. - Returns None if key not found or value is empty. - """ - pat = re.compile(r'"' + re.escape(key) + r'"\s*:\s*', re.DOTALL) - m = pat.search(text) - if not m: - return None - val_start = m.end() - # Skip leading backslash-escape if the value starts with \" (nested JSON string) - if val_start < len(text) and text[val_start] == '\\': - val_start += 1 - # Check if value is a string - if val_start < len(text) and text[val_start] == '"': - s = val_start + 1 - buf = [] - while s < len(text): - ch = text[s] - if ch == '\\' and s + 1 < len(text): - buf.append(text[s+1]) - s += 2 - elif ch == '"': - return ''.join(buf) - elif ch in end_chars and not buf: - return None - else: - buf.append(ch) - s += 1 - return ''.join(buf) - # Object value: find balanced brace - if val_start < len(text) and text[val_start] == '{': - end = _find_balanced_brace(text, val_start) - if end > val_start: - return text[val_start:end+1] - return None - - def _extract_args(text): - """Extract arguments value from tool-call JSON, handling multiple malformed formats. - - [FIX 6] THREE-TIER PARSER — solves double-wrapped arguments bug: - Model generates arguments in TWO different escaped forms: - A) Unescaped: "arguments": "{"cmd": "curl ...", "sp": "allow_all"}" - → naive brace-counting finds boundaries correctly - B) Escaped: "arguments": "{\\"cmd\\": \\"curl...\\"}" - → json.loads fails on \\ at structural level - → unescape \\" → " and retry - → unicode_escape decode and retry - - Returns the raw JSON string (after best-effort unescaping). - Caller does json.loads() on the result. - If all 3 tiers fail, returns raw text (caller handles as fallback). - """ - m = re.search(r'"(?:arguments|input)"\s*:\s*"?', text) - if not m: - return None - start = m.end() - if start < len(text) and text[start] == '"': - start += 1 - if start >= len(text) or text[start] != '{': - return None - depth = 0 - i = start - while i < len(text): - ch = text[i] - if ch == '{': - depth += 1 - elif ch == '}': - depth -= 1 - if depth == 0: - raw = text[start:i+1] - - # Try JSON.parse as-is - try: - json.loads(raw) - return raw - except json.JSONDecodeError: - pass - - # Try after unescaping inner \" -> " - unescaped = raw.replace('\\"', '"') - try: - json.loads(unescaped) - return unescaped - except json.JSONDecodeError: - pass - - # Try after also unescaping \\n -> \n etc - try: - fixed = raw.encode().decode('unicode_escape') - json.loads(fixed) - return fixed - except Exception: - pass - - # Give up — return raw text - return raw - i += 1 - return None - - def _extract_raw_json_tool_calls(t): - """[FIX 5] Extract raw JSON tool-call objects from free text. - - Finds "type":"tool-call" (or tool_call/function_call) in text, then extracts - name/id/arguments/sandbox_permissions/justification via field-level regex. - - Delegates to _extract_args() for the arguments field (handles unescaped + escaped JSON). - Delegates to _extract_field() for name/id/sandbox_permissions/justification - (with FIX 7 for leading-backslash handling). - - Normalizes sandbox_permissions to valid values (use_default|require_escalated|with_user_approval) - [FIX 6] Prevents double-wrapped args: {"cmd": "{\"cmd\": \"curl...\"}"} - """ - results = [] - idx = 0 - while True: - m = re.search(r'"type"\s*:\s*"(tool-call|tool_call|function_call)"', t[idx:]) - if not m: - break - tc_pos = idx + m.start() - snippet = t[tc_pos:] - idx = tc_pos + 1 - tc_type = m.group(1) - tc_name = _extract_field(snippet, "name") - if not tc_name: - continue - tc_id = _extract_field(snippet, "id") - - # [FIX 20] Support explore / explore_agent in raw JSON tool calls - is_explore = tc_name.lower() in ("explore", "explore_agent") - - if is_explore: - # Build explore command from the whole snippet/arguments - explore_cmd, explore_just = _build_explore_cmd_local(snippet) - if explore_cmd: - args = {"cmd": explore_cmd} - if explore_just: - args["justification"] = explore_just - else: - args = {"cmd": "echo 'explore: unable to extract repository URL'", "justification": "Fallback for explore tool call without URL."} - tool_name = "exec_command" - else: - # [FIX 19] Translate execute_request and other variations to exec_command (CLI only supports exec_command) - tool_name = "exec_command" if tc_name.lower() in ("exec", "bash", "shell", "terminal", "run_command", "execute_request", "execute_command", "run_shell_command", "run_shell", "run") else tc_name - args_raw = _extract_args(snippet) or _extract_field(snippet, "arguments") or _extract_field(snippet, "input") or "{}" - try: - args = json.loads(args_raw) if args_raw.startswith('{') else {"cmd": args_raw} - except Exception: - args = {"cmd": args_raw} - if "cmd" not in args or not args["cmd"]: - args["cmd"] = str(args) - # [FIX 11] Self-healing: unwrap double-wrapped cmd values - args["cmd"] = _unwrap_cmd(args.get("cmd", "")) - - # Normalize sandbox_permissions to valid values - _VALID_SP = frozenset({"use_default", "require_escalated", "with_user_approval"}) - if "sandbox_permissions" in args: - spv = args["sandbox_permissions"] - if isinstance(spv, dict): - args["sandbox_permissions"] = "require_escalated" if spv.get("require_escalated") else "use_default" - elif isinstance(spv, str) and spv not in _VALID_SP: - args["sandbox_permissions"] = "require_escalated" - else: - # Fallback: extract from raw snippet (model puts it at top level) - sp_raw = _extract_field(snippet, "sandbox_permissions") - if sp_raw: - try: - sp_obj = json.loads(sp_raw) if sp_raw.startswith('{') else {"require_escalated": bool(sp_raw)} - if isinstance(sp_obj, dict) and sp_obj.get("require_escalated"): - args["sandbox_permissions"] = "require_escalated" - except Exception: - pass - if "justification" not in args: - just_raw = _extract_field(snippet, "justification") - if just_raw: - args["justification"] = just_raw - results.append({ - "full_match": snippet, - "name": tool_name, - "arguments": json.dumps(args, ensure_ascii=False), - }) - return results - - for pat in patterns: - for m in re.finditer(pat, text, re.DOTALL | re.IGNORECASE): - if pat.startswith("\s]+)", body, re.IGNORECASE) - raw_name = raw_name or (nm.group(1) if nm else "bash") - params = {} - body_stripped = body.strip() - if body_stripped.startswith("{"): - try: - obj = json.loads(body_stripped) - cmd = obj.get("command") or obj.get("cmd") or "" - cmd = _unwrap_cmd(cmd) # [FIX 11] - if cmd: - # [FIX 19] Translate execute_request and other variations to exec_command (CLI only supports exec_command) - tool_name = "exec_command" if raw_name.lower() in ("exec", "bash", "shell", "terminal", "run_command", "execute_request", "execute_command", "run_shell_command", "run_shell", "run") else raw_name - args = {"cmd": cmd} - sp = obj.get("sandbox_permissions") - if isinstance(sp, dict) and sp.get("require_escalated"): - args["sandbox_permissions"] = "require_escalated" - elif isinstance(sp, str): - args["sandbox_permissions"] = sp - if obj.get("justification"): - args["justification"] = obj.get("justification") - calls.append({"full_match": m.group(0), "name": tool_name, "arguments": json.dumps(args)}) - continue - except Exception: - pass - for pm in re.finditer(r"(.*?)", body, re.DOTALL | re.IGNORECASE): - key = pm.group(1) or pm.group(2) or "text" - params[key] = _strip_xmlish_tags(pm.group(3)).strip() - - # [FIX 20] Support explore / explore_agent in XML tool calls - is_explore = raw_name.lower() in ("explore", "explore_agent") - if is_explore: - explore_cmd, explore_just = _build_explore_cmd_local(body) - if explore_cmd: - cmd = explore_cmd - params["justification"] = explore_just - else: - cmd = "" - else: - cmd = params.get("command") or params.get("cmd") or "" - - if not cmd and body_stripped.startswith("{"): - cm = re.search(r'"(?:command|cmd)"\s*:\s*"(.*?)"\s*,\s*"(?:sandbox_permissions|justification|prefix_rule)"', body, re.DOTALL) - if not cm: - cm = re.search(r'"(?:command|cmd)"\s*:\s*"(.*?)"\s*}', body, re.DOTALL) - if cm: - cmd = cm.group(1) - cmd = cmd.replace('\\n', '\n').replace('\\"', '"').strip() - cmd = _unwrap_cmd(cmd) # [FIX 11] - if re.search(r'"sandbox_permissions"\s*:\s*\{\s*"require_escalated"\s*:\s*true\s*\}', body, re.DOTALL): - params["sandbox_permissions"] = "require_escalated" - jm = re.search(r'"justification"\s*:\s*"(.*?)"\s*(?:,|})', body, re.DOTALL) - if jm: - params["justification"] = jm.group(1).replace('\\n', '\n').replace('\\"', '"').strip() - if not cmd: - stripped = _strip_xmlish_tags(body) - lines = [ln.strip() for ln in stripped.splitlines() if ln.strip()] - for i, ln in enumerate(lines): - if re.match(r"^(curl|wget|python3?|node|npm|pnpm|yarn|cat|ls|find|grep|rg|sed|awk|git|mkdir|touch|printf|echo)\b", ln): - cmd = "\n".join(lines[i:]) - break - if not cmd and lines: - cmd = "\n".join(lines) - if not cmd: - continue - # [FIX 19] Translate execute_request and other variations to exec_command (CLI only supports exec_command) - # [FIX 20] Translate explore and explore_agent to exec_command - tool_name = "exec_command" if raw_name.lower() in ("exec", "bash", "shell", "terminal", "run_command", "execute_request", "execute_command", "run_shell_command", "run_shell", "run", "explore", "explore_agent") else raw_name - args = {"cmd": _unwrap_cmd(cmd)} # [FIX 11] all paths must unwrap - if params.get("sandbox_permissions"): - args["sandbox_permissions"] = params["sandbox_permissions"] - if params.get("justification"): - args["justification"] = params["justification"] - calls.append({"full_match": m.group(0), "name": tool_name, "arguments": json.dumps(args)}) - - # Also extract raw JSON tool-call objects embedded in free text - calls.extend(_extract_raw_json_tool_calls(text)) - - # [FIX 18] Native blocks from the model (used for checklist/task tracking) - # The model outputs a task checklist in a custom XML tag block: - # - # [{"id":"1","status":"in_progress","description":"..."}] - # - # We parse this and map it to a standard 'TodoWrite' tool call so the CLI agent loop continues execution. - for m in re.finditer(r"(.*?)", text, re.DOTALL | re.IGNORECASE): - body = (m.group(1) or "").strip() - if not body: - continue - todos_match = re.search(r"(.*?)", body, re.DOTALL | re.IGNORECASE) - if not todos_match: - continue - raw_todos_json = todos_match.group(1).strip() - try: - raw_todos = json.loads(raw_todos_json) - except Exception as e: - print(f"[translate-proxy] [FIX 18] Failed to parse JSON: {e}", file=sys.stderr) - raw_todos = None - if isinstance(raw_todos, list): - parsed_todos = [] - for item in raw_todos: - if isinstance(item, dict): - desc = item.get("description") or item.get("content") or "" - parsed_todos.append({ - "content": desc, - "activeForm": item.get("activeForm") or desc, - "status": item.get("status") or "pending" - }) - calls.append({ - "full_match": m.group(0), - "name": "TodoWrite", - "arguments": json.dumps({"todos": parsed_todos}, ensure_ascii=False) - }) - - # [FIX 11] Self-healing: last-chance sanitization pass on ALL extracted calls - calls = _sanitize_tool_calls(calls) - return calls - -def _sanitize_tool_calls(calls): - """[FIX 11/T3] Post-extraction self-healing validation layer. - - Runs AFTER all extraction paths (XML, raw JSON, regex) have produced their - tool calls. This is the final safety net before calls are returned to the - streaming/response builder. - - Validates and repairs: - - Double/triple-wrapped cmd values (recursive unwrap) - - cmd that looks like JSON object/string instead of shell command - - cmd containing escaped newlines or quotes that would break bash - - Empty or whitespace-only cmd → replaced with diagnostic string - - Logs warnings for any repair made (visible in stderr/proxy logs). - Returns sanitized list (may be shorter if irreparable calls are dropped). - """ - cleaned = [] - for i, call in enumerate(calls): - # [FIX 18] Skip sanitization pass for non-shell tool calls (e.g., TodoWrite) - # Sanitization specifically validates and repairs command shell executions (the 'cmd' argument). - # Running it on other tools without a 'cmd' parameter (like TodoWrite) would falsely flag - # them as containing JSON garbage or empty commands, corrupting their actual parameters. - if call.get("name") != "exec_command": - cleaned.append(call) - continue - - try: - args_raw = call.get("arguments", "{}") - if isinstance(args_raw, str): - args = json.loads(args_raw) - else: - args = dict(args_raw) - except Exception: - cleaned.append(call) - continue - cmd = args.get("cmd", "") - repaired = False - - # Detect and unwrap nested JSON cmd values (up to 4 levels deep) - unwrapped = _unwrap_cmd(cmd) - if unwrapped != cmd: - cmd = unwrapped - args["cmd"] = cmd - repaired = True - - # Detect cmd that is still a JSON object (unwrap missed it or deeper nesting) - if isinstance(cmd, str) and cmd.strip().startswith("{"): - try: - inner = json.loads(cmd) - if isinstance(inner, dict): - for key in ("cmd", "command", "c"): - if key in inner and isinstance(inner[key], str): - args["cmd"] = inner[key] - repaired = True - break - except Exception: - pass - - # Detect cmd that looks like a JSON-encoded string with backslash escapes - _cmd = args.get("cmd", "") - if _cmd and ('\\"' in _cmd or "\\n" in _cmd or _cmd.count("{") > _cmd.count("}")): - try: - decoded = _cmd.encode().decode("unicode_escape") - if decoded != _cmd and not decoded.startswith("{"): - args["cmd"] = decoded - repaired = True - except Exception: - pass - - # Final guard: if cmd is empty or just JSON garbage, make it obvious - _final_cmd = args.get("cmd", "") - if not _final_cmd or _final_cmd.strip() in ("{}", "null", "None", ""): - _safe_preview = args_raw[:200].replace('"', "'").replace('\\', '/') - args["cmd"] = f"# [CC-SANITIZER] empty cmd recovered from: {_safe_preview}" - repaired = True - elif _final_cmd.startswith("{") and len(_final_cmd) < 500: - # Still looks like JSON — likely unrecoverable, flag it - _safe_preview = _final_cmd.replace('"', "'").replace('\\', '/') - args["cmd"] = f"# [CC-SANITIZER] suspicious cmd (still JSON): {_safe_preview}" - repaired = True - - if repaired: - print(f"[translate-proxy] [CC-SANITIZER] repaired tool call #{i}: " - f"name={call.get('name')} cmd_preview={str(args.get('cmd',''))[:120]}", - file=sys.stderr) - - call["arguments"] = json.dumps(args, ensure_ascii=False) - cleaned.append(call) - - return cleaned - -def _parse_cc_line(line): - """Parse a raw line from CommandCode /alpha/generate, stripping SSE data: prefix.""" - stripped = line.strip() - if not stripped: - return None - if stripped.startswith("data: "): - stripped = stripped[6:] - elif stripped.startswith("data:"): - stripped = stripped[5:] - if not stripped or stripped == "[DONE]": - return None - try: - return json.loads(stripped) - except json.JSONDecodeError: - return None - - -def _iter_cc_events(stream): - """Yield parsed JSON events from a CommandCode /alpha/generate stream. - Handles raw JSON lines, SSE data: events, and multi-event chunks. - """ - buf = "" - 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) - d = _parse_cc_line(line) - if d is not None: - yield d - # Process remaining buffer (non-streaming single-JSON response) - if buf.strip(): - if buf.strip().startswith("{"): - d = _parse_cc_line(buf) - if d is not None: - yield d - else: - for line in buf.strip().split("\n"): - d = _parse_cc_line(line) - if d is not None: - yield d - - -def cc_resp_to_responses(cc_lines, model, resp_id=None): - text = "" - usage = {} - if isinstance(cc_lines, str): - cc_lines = [cc_lines] - for line in cc_lines: - d = _parse_cc_line(line) - if d is None: - continue - t = d.get("type", "") - if t == "text-delta": - text += d.get("text", "") - elif t == "finish-step": - u = d.get("usage", {}) - usage = { - "input_tokens": u.get("inputTokens", 0), - "output_tokens": u.get("outputTokens", 0), - "total_tokens": u.get("inputTokens", 0) + u.get("outputTokens", 0), - } - outputs = [] - if text: - outputs.append({"type": "message", "id": uid("msg"), "role": "assistant", - "status": "completed", - "content": [{"type": "output_text", "text": text, "annotations": []}]}) - return {"id": resp_id or uid("resp"), "object": "response", "created": int(time.time()), - "model": model, "status": "completed", "output": outputs, - "usage": {"input_tokens": usage.get("input_tokens", 0), - "output_tokens": usage.get("output_tokens", 0), - "total_tokens": usage.get("total_tokens", 0), - "input_tokens_details": {"cached_tokens": 0}}} - -def cc_stream_to_sse(cc_stream, model, req_id): - resp_id = req_id or uid("resp") - msg_id = uid("msg") - text_buf = "" - - yield emit("response.created", {"type": "response.created", - "response": {"id": resp_id, "object": "response", "model": model, - "status": "in_progress", "created": int(time.time()), "output": []}}) - yield emit("response.in_progress", {"type": "response.in_progress", "response": {"id": resp_id}}) - - total_usage = {} - _event_types_seen = set() - _debug_log_path = os.path.expanduser("~/.cache/codex-proxy/cc-debug.log") - _debug_fh = open(_debug_log_path, "a") # [FIX 14] always write debug to FILE (not just stderr which may be piped) - _deflog = lambda *a, **kw: print(*a, file=_debug_fh, flush=True, **kw) - - for d in _iter_cc_events(cc_stream): - t = d.get("type", "") - _event_types_seen.add(t) - - if t == "text-delta": - txt = d.get("text", "") - if txt: - text_buf += txt - - elif t == "finish-step": - u = d.get("usage", {}) - total_usage = { - "input_tokens": u.get("inputTokens", 0), - "output_tokens": u.get("outputTokens", 0), - "total_tokens": u.get("inputTokens", 0) + u.get("outputTokens", 0), - } - elif t not in ("text-delta", "finish-step"): - _deflog(f"[CC-DEBUG] unexpected event type: {t} keys={list(d.keys())[:5]} data={str(d)[:200]}") - - _deflog(f"[CC-DEBUG] stream ended. event_types={_event_types_seen} text_buf_len={len(text_buf)}") - - parsed_tool_calls = _parse_commandcode_text_tool_calls(text_buf) - _deflog(f"[CC-DEBUG] text_buf len={len(text_buf)} parsed_tool_calls={len(parsed_tool_calls)} " - f"text_preview={text_buf[:500]!r}") - if parsed_tool_calls: - for ti, tc in enumerate(parsed_tool_calls): - _deflog(f"[CC-DEBUG] tool_call[{ti}] name={tc.get('name')} args_preview={tc.get('arguments','')[:150]!r}") - - # [FIX 13] FALLBACK: if parser returned empty but text contains tool-call patterns, - # force-extract using regex. This catches cases where model output format - # doesn't match any of our named patterns (XML/raw JSON/function=). - if not parsed_tool_calls and len(text_buf) > 20: - _has_tc_signals = ( - '"type"' in text_buf and ('tool-call' in text_buf or 'tool_call' in text_buf or 'function_call' in text_buf) - ) or ( - ' 10: - _synth_cmd = None - _synth_just = None - _tl = text_buf.lower() - - # Heuristic 1: URL in text → fetch it - _url_in_text = re.search(r"https?://[^\s\]'\\>\",]+", text_buf) - if _url_in_text: - _synth_url = _url_in_text.group(0).rstrip(")].,;'\\\"") - if _IS_WINDOWS: - _synth_cmd = f"Invoke-WebRequest -Uri '{_synth_url}' -UseBasicParsing -TimeoutSec 15 | Select-Object -ExpandProperty Content | Select-Object -First 200" - else: - _synth_cmd = f"curl -sL --max-time 15 '{_synth_url}' 2>/dev/null | head -200" - _synth_just = "Auto-synthesized: URL detected in text, fetching" - - # Heuristic 2: File path references → list or read - if not _synth_cmd: - _file_m = re.search(r"(?:read|open|view|check|examine|cat|show)\s+(?:the\s+)?(?:file\s+)?[`'\"]?(/[^\s'\"]+\.\w+)", _tl) - if _file_m: - _fpath = _file_m.group(1) - if _IS_WINDOWS: - _synth_cmd = f"Get-Content '{_fpath}' -ErrorAction SilentlyContinue | Select-Object -First 200; if (-not $?) {{ Get-Item '{_fpath}' | Select-Object Name,Length,LastWriteTime }}" - else: - _synth_cmd = f"cat '{_fpath}' 2>/dev/null | head -200 || ls -la '{_fpath}'" - _synth_just = f"Auto-synthesized: file reference detected ({_fpath})" - - # Heuristic 3: Shell command mentioned in backticks or quotes - if not _synth_cmd: - _shell_m = re.search(r"[`'\"]((?:curl|wget|git|npm|pip|python|ls|cat|grep|find|mkdir|cd|rm|cp|mv|chmod|docker|make|cargo|go)\s[^\s`'\"]+)", text_buf) - if _shell_m: - _synth_cmd = _shell_m.group(1) - _synth_just = "Auto-synthesized: shell command detected in text" - - # Heuristic 4: "explore" or "fetch" intent + last user URL - if not _synth_cmd and ("explore" in _tl or "fetch" in _tl or "investigate" in _tl or "repository" in _tl): - for _prev_url in _last_user_urls: - _url_m2 = re.search(r"https?://[^\s\]'\\>\",]+", _prev_url) - if _url_m2: - _pu = _url_m2.group(0).rstrip(")].,;'\\\"") - _ecmd, _ejust = _build_explore_cmd(_pu) - if _ecmd: - _synth_cmd = _ecmd - _synth_just = _ejust or "Auto-synthesized: explore intent with last user URL" - break - - # Heuristic 5: Generic "I need to" / "let me" / "I'll" intent with command-like text - if not _synth_cmd: - _intent_m = re.search(r"(?:I(?:'ll| will| need to| should)|let me|please)\s+(.+?)(?:\.|!|\n|$)", _tl, re.IGNORECASE) - if _intent_m: - _intent_text = _intent_m.group(1).strip() - if len(_intent_text) > 10 and len(_intent_text) < 200: - if _IS_WINDOWS: - _synth_cmd = f"Write-Output 'Stuck recovery: model intent was: {_intent_text[:100]}'" - else: - _synth_cmd = f"echo 'Stuck recovery: model intent was: {_intent_text[:100]}'" - _synth_just = f"Auto-synthesized from intent text: {_intent_text[:80]}" - - if _synth_cmd: - parsed_tool_calls = [{ - "full_match": "__synth_stuck_recovery__", - "name": "exec_command", - "arguments": json.dumps({"cmd": _synth_cmd, "justification": _synth_just or "Auto-synthesized stuck recovery"}, ensure_ascii=False), - }] - _deflog(f"[CC-DEBUG] [STUCK-RECOVERY] Synthesized: cmd={_synth_cmd[:120]!r}") - print(f"[CC-DEBUG] [STUCK-RECOVERY] Synthesized command from text intent", file=sys.stderr, flush=True) - - # Also log to stderr for visibility when not piped - print(f"[CC-DEBUG] text_buf={len(text_buf)} chars, tool_calls={len(parsed_tool_calls)}", file=sys.stderr, flush=True) - - try: - _debug_fh.close() - except Exception: - pass - clean_text = text_buf - for tc in parsed_tool_calls: - clean_text = clean_text.replace(tc["full_match"], "") - clean_text = clean_text.strip() - - if clean_text: - yield emit("response.output_item.added", {"type": "response.output_item.added", - "item": {"type": "message", "id": msg_id, "role": "assistant", "status": "in_progress", "content": []}}) - yield emit("response.content_part.added", {"type": "response.content_part.added", - "part": {"type": "output_text", "text": "", "annotations": []}, "item_id": msg_id}) - yield emit("response.output_text.delta", {"type": "response.output_text.delta", - "delta": clean_text, "item_id": msg_id, "content_index": 0}) - yield emit("response.output_text.done", {"type": "response.output_text.done", - "text": clean_text, "item_id": msg_id, "content_index": 0}) - yield emit("response.content_part.done", {"type": "response.content_part.done", - "part": {"type": "output_text", "text": clean_text, "annotations": []}, "item_id": msg_id}) - yield emit("response.output_item.done", {"type": "response.output_item.done", - "item": {"type": "message", "id": msg_id, "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": clean_text, "annotations": []}]}}) - - function_outputs = [] - for tc in parsed_tool_calls: - fid = uid("fc") - call_id = uid("call") - item = {"type": "function_call", "id": fid, "call_id": call_id, - "name": tc["name"], "arguments": tc["arguments"], "status": "completed"} - function_outputs.append(item) - yield emit("response.output_item.added", {"type": "response.output_item.added", "item": item}) - yield emit("response.function_call_arguments.done", {"type": "response.function_call_arguments.done", - "item_id": fid, "name": tc["name"], "arguments": tc["arguments"]}) - yield emit("response.output_item.done", {"type": "response.output_item.done", "item": item}) - - final_out = [] - if clean_text: - final_out.append({"type": "message", "id": msg_id, "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": clean_text, "annotations": []}]}) - final_out.extend(function_outputs) - yield emit("response.completed", {"type": "response.completed", - "response": {"id": resp_id, "object": "response", "model": model, - "status": "completed", "created": int(time.time()), "output": final_out, - "usage": total_usage}}) - -# ═══════════════════════════════════════════════════════════════════ -# Auto-sensing provider adapter -# ═══════════════════════════════════════════════════════════════════ - -_SENTINEL = object() - -@dataclasses.dataclass -class ProviderSchema: - """Describes what message formats a provider supports. - - Populated by probing the endpoint and/or analyzing error responses. - Cached in provider-caps.json so probing only happens once per provider. - """ - supported_roles: tuple = ("user", "assistant") - content_type: str = "string" # "string" | "array" - content_block_types: tuple = () # e.g. ("text", "tool_result", "tool-call") - tool_result_style: str = "inline" # "inline" | "tool_result_block" | "anthropic" - tool_call_style: str = "openai_function" # "openai_function" | "tool-call" | "anthropic_tool_use" - accepts_tool_role: bool = False - accepts_system_role: bool = True - cc_body_wrap: bool = False # needs {config, params, threadId} wrapping - field_names: dict = dataclasses.field(default_factory=dict) - auth_type: str = "" # "bearer" | "x-api-key" | "custom" - auth_header: str = "Authorization" # header name for auth - auth_scheme: str = "Bearer " # prefix for auth value - tool_decl_format: str = "openai" # "openai" | "anthropic" | "command_code" - param_names: dict = dataclasses.field(default_factory=lambda: { - "max_tokens": "max_tokens", - "temperature": "temperature", - "top_p": "top_p", - }) - response_format: str = "auto" # "sse" | "raw_json" | "ndjson" | "auto" - stream_format: str = "auto" # "sse_data" | "sse_event" | "raw_lines" | "json_lines" - - def hints(self) -> dict: - """Return a dict for storing in provider-caps.json.""" - d = {} - for k, v in dataclasses.asdict(self).items(): - if isinstance(v, (list, tuple)) and not v: - continue - if isinstance(v, dict) and not v: - continue - if v is False: - continue - if v == "": - continue - if v == "auto": - continue - d[k] = v - return d - - -class ErrorAnalyzer: - """Parse upstream error responses to infer provider schema. - Analyzes 400, 401, 422 errors for hints about auth, roles, content format, - parameter names, field names, tool format, and response format. - """ - - @staticmethod - def analyze(error_text: str, current: ProviderSchema = None) -> dict: - hints = {} - if not error_text: - return hints - err = error_text.lower() - - # ── Auth detection (401 errors) ── - if re.search(r"unauthorized|invalid.*api.?key|missing.*api.?key|x-api-key", err): - hints["auth_type"] = "x-api-key" - hints["auth_header"] = "x-api-key" - hints["auth_scheme"] = "" - elif re.search(r"invalid.*bearer|bearer.*token|authorization.*header|invalid.*token", err): - hints["auth_type"] = "bearer" - hints["auth_header"] = "Authorization" - hints["auth_scheme"] = "Bearer " - - # ── Role validation ── - if re.search(r"role.*expected.*(?:user|assistant)", err): - hints["accepts_tool_role"] = False - hints["accepts_function_role"] = False - - if re.search(r"role.*(?:tool|function).*(?:invalid|not.*(?:support|allow))", err): - hints["accepts_tool_role"] = False - hints["accepts_function_role"] = False - - if re.search(r"role.*system.*(?:invalid|not.*(?:support|allow))", err): - hints["accepts_system_role"] = False - - # ── Content format (top-level only, not content[i].xxx) ── - if re.search(r'params\.messages\[\d+\]\.content', err): - # Explicit path to content field in a messages array (e.g. /alpha/generate) - if re.search(r"expected string.*received array", err): - hints["content_type"] = "string" - hints["tool_result_style"] = "inline" # no tool_result blocks allowed - elif re.search(r"expected array.*received string", err): - hints["content_type"] = "array" - elif re.search(r"(? ProviderSchema: - for k, v in hints.items(): - if k == "field_names" and isinstance(v, dict): - schema.field_names.update(v) - elif k == "param_names" and isinstance(v, dict): - schema.param_names.update(v) - elif hasattr(schema, k): - setattr(schema, k, v) - return schema - - -def _schema_cache_key(target_url=None, backend=None, model=None): - host = urllib.parse.urlparse(target_url or TARGET_URL).netloc.lower() - return f"auto-schema|{backend or BACKEND}|{host}|{model or '*'}" - - -def _load_schema(target_url=None, backend=None, model=None): - caps = _load_provider_caps() - key = _schema_cache_key(target_url, backend, model) - raw = caps.get(key) - generic = caps.get(_schema_cache_key(target_url, backend, model="*")) - data = raw or generic or {} - if not data: - return ProviderSchema() - # Staleness check: re-learn after 24h (86400s) - updated = data.get("_updated", 0) - if isinstance(updated, (int, float)) and time.time() - updated > 86400: - print(f"[auto-sense] cached schema stale ({int(time.time()-updated)}s old), re-learning", file=sys.stderr) - return ProviderSchema() - return ProviderSchema( - supported_roles=tuple(data.get("supported_roles", ("user", "assistant"))), - content_type=data.get("content_type", "string"), - content_block_types=tuple(data.get("content_block_types", ())), - tool_result_style=data.get("tool_result_style", "inline"), - tool_call_style=data.get("tool_call_style", "openai_function"), - accepts_tool_role=data.get("accepts_tool_role", False), - accepts_system_role=data.get("accepts_system_role", True), - cc_body_wrap=data.get("cc_body_wrap", False), - field_names=dict(data.get("field_names", {})), - auth_type=data.get("auth_type", ""), - auth_header=data.get("auth_header", "Authorization"), - auth_scheme=data.get("auth_scheme", "Bearer "), - tool_decl_format=data.get("tool_decl_format", "openai"), - param_names=dict(data.get("param_names", { - "max_tokens": "max_tokens", - "temperature": "temperature", - "top_p": "top_p", - })), - response_format=data.get("response_format", "auto"), - stream_format=data.get("stream_format", "auto"), - ) - - -def _save_schema(schema: ProviderSchema, target_url=None, backend=None, model=None): - caps = _load_provider_caps() - key = _schema_cache_key(target_url, backend, model) - caps[key] = schema.hints() - caps[key]["_updated"] = time.time() - caps[key]["_backend"] = backend or BACKEND - _save_provider_caps() - print(f"[auto-sense] cached schema {key}", file=sys.stderr) - - -class SchemaAdapter: - """Convert Responses API messages based on a detected ProviderSchema.""" - - def __init__(self, schema: ProviderSchema): - self.s = schema - - def convert(self, input_data, instructions=""): - if self.s.content_type == "string" and not self.s.content_block_types: - return self._to_plain_string(input_data, instructions) - return self._to_content_blocks(input_data, instructions) - - def _to_plain_string(self, input_data, instructions=""): - """Fallback: user/assistant string content — no tool roles.""" - msgs = [] - if instructions and self.s.accepts_system_role: - msgs.append({"role": "system", "content": instructions}) - elif instructions: - msgs.append({"role": "user", "content": instructions}) - if isinstance(input_data, str): - msgs.append({"role": "user", "content": input_data}) - return msgs - if not isinstance(input_data, list): - return msgs - last_flushed = [] - pending = [] - for item in input_data: - t = item.get("type") - if t == "function_call": - cid = item.get("call_id") or item.get("id") or uid("fc") - pending.append({"id": cid, "name": item.get("name", ""), - "arguments": item.get("arguments", "{}")}) - continue - if pending: - last_flushed = [p["id"] for p in pending] - msgs.append({"role": "assistant", "content": None, - "tool_calls": [{"id": p["id"], "type": "function", - "function": {"name": p["name"], - "arguments": p["arguments"]}} - for p in pending]}) - pending = [] - if t == "message": - role = "user" if item.get("role") in ("user", "developer") else "assistant" - text = _extract_text(item.get("content", [])) - if text: - msgs.append({"role": role, "content": text}) - elif t == "function_call_output": - out = item.get("output", "") - if not isinstance(out, str): - out = json.dumps(out, ensure_ascii=False) - msgs.append({"role": "user", "content": out[:8000]}) - if pending: - last_flushed = [p["id"] for p in pending] - msgs.append({"role": "assistant", "content": None, - "tool_calls": [{"id": p["id"], "type": "function", - "function": {"name": p["name"], - "arguments": p["arguments"]}} - for p in pending]}) - return msgs - - def _to_content_blocks(self, input_data, instructions=""): - msgs = [] - pending_tc = [] - tool_name_by_id = {} - last_ids = [] - - def flush(): - nonlocal last_ids - if not pending_tc: - return - last_ids = [t["id"] for t in pending_tc] - msgs.append({"role": "assistant", "content": pending_tc}) - pending_tc.clear() - - _str = self.s.content_type == "string" - - if instructions: - msgs.append({"role": "user", "content": instructions if _str else [{"type": "text", "text": instructions}]}) - - if isinstance(input_data, str): - msgs.append({"role": "user", "content": input_data if _str else [{"type": "text", "text": input_data}]}) - return msgs - if not isinstance(input_data, list): - return msgs - - for item in input_data: - t = item.get("type") - if t == "function_call": - cid = item.get("call_id") or item.get("id") or uid("call") - nm = item.get("name") or "exec_command" - tool_name_by_id[cid] = nm - tc_block = self._tool_call_block(cid, nm, item.get("arguments", "{}")) - if tc_block: - pending_tc.append(tc_block) - continue - flush() - if t == "message": - role = "user" if item.get("role") in ("user", "developer") else "assistant" - text = _extract_text(item.get("content", [])) - if text: - msgs.append({"role": role, "content": text if _str else [{"type": "text", "text": text}]}) - elif t == "function_call_output": - cid = item.get("call_id") or item.get("id") or "" - if not cid and last_ids: - idx = sum(1 for m in msgs for c in (m.get("content") or []) - if isinstance(c, dict) and c.get("type") in - ("tool_result", "tool-result")) - if idx < len(last_ids): - cid = last_ids[idx] - out = item.get("output", "") - if not isinstance(out, str): - out = json.dumps(out, ensure_ascii=False) - tr = self._tool_result_block(cid, out) - if tr: - msgs.append({"role": "user", "content": [tr]}) - flush() - return msgs - - def _tool_call_block(self, cid, name, args): - style = self.s.tool_call_style - fn = self.s.field_names - if style == "tool-call": - return { - "type": fn.get("tool_call_type", "tool-call"), - fn.get("tool_call_id_field", "id"): cid, - fn.get("tool_call_name_field", "name"): name, - fn.get("tool_call_args_field", "arguments"): args, - } - elif style == "anthropic_tool_use": - try: - parsed = json.loads(args) - except Exception: - parsed = {} - return { - "type": fn.get("tool_use_type", "tool_use"), - fn.get("tool_call_id_field", "id"): cid, - fn.get("tool_call_name_field", "name"): name, - fn.get("tool_call_args_field", "input"): parsed, - } - else: - return None # handled as OpenAI function call - - def _tool_result_block(self, cid, output): - style = self.s.tool_result_style - fn = self.s.field_names - if style == "tool_result_block": - return { - "type": fn.get("tool_result_type", "tool_result"), - fn.get("tool_use_id", "tool_use_id"): cid or "", - "content": [{"type": "text", "text": output[:8000]}], - } - elif style == "anthropic": - return { - "type": fn.get("tool_result_type", "tool_result"), - fn.get("tool_use_id", "tool_use_id"): cid or "", - "content": output[:8000], - } - return None # inline — handled by _to_plain_string - - -def _sanitize_err_body(body): - """Sanitize upstream error body: strip HTML, truncate, remove control chars.""" - if not body: - return "" - s = re.sub(r'<[^>]+>', '', body) - s = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f]', '', s) - s = s.strip()[:1000] - return s - - -def _extract_text(content): - if isinstance(content, str): - return content - if not isinstance(content, list): - return "" - parts = [] - for p in content: - if isinstance(p, str): - parts.append(p) - elif isinstance(p, dict) and p.get("type") in ("input_text", "output_text", "text"): - parts.append(p.get("text", "")) - return "".join(parts) - - -# ═══════════════════════════════════════════════════════════════════ -# HTTP Server -# ═══════════════════════════════════════════════════════════════════ - -_MAX_REQLOG_LINES = 2000 - -def _log_resp(resp_id, status, output): - try: - import datetime as _dt - _lp = os.path.join(_LOG_DIR, "requests.log") - with open(_lp, "a", encoding="utf-8") as _f: - _f.write(f" RESPONSE id={resp_id} status={status}\n") - if output: - for o in output: - ot = o.get("type") - if ot == "message": - _f.write(f" -> message: {o.get('content',[{}])[0].get('text','')[:200]}\n") - elif ot == "function_call": - _f.write(f" -> function_call: {o.get('name')}({o.get('arguments','')[:120]})\n") - else: - _f.write(f" -> {ot}\n") - _f.write(f"{'='*60}\n") - _f.flush() - _f.seek(0) - lines = _f.readlines() - if len(lines) > _MAX_REQLOG_LINES: - with open(_lp, "w", encoding="utf-8") as _f2: - _f2.writelines(lines[-_MAX_REQLOG_LINES:]) - except Exception: - pass - -class ConnectionTracker: - def __enter__(self): - global _active_connections - with _active_connections_lock: - _active_connections += 1 - def __exit__(self, *a): - global _active_connections - with _active_connections_lock: - _active_connections -= 1 - -class RequestTracker: - def __init__(self, request_id): - self.request_id = request_id - self.cancelled = threading.Event() - - def __enter__(self): - if self.request_id: - with _active_requests_lock: - _active_requests[self.request_id] = self - return self - - def __exit__(self, *a): - if self.request_id: - with _active_requests_lock: - _active_requests.pop(self.request_id, None) - -def _cancel_request(request_id): - with _active_requests_lock: - req = _active_requests.get(request_id) - if not req: - return False - req.cancelled.set() - return True - -def _handle_shutdown_signal(signum, frame): - global _shutdown_requested - _shutdown_requested = True - print("[proxy] shutdown requested; draining connections", file=sys.stderr) - def _drain(): - deadline = time.time() + 5 - while time.time() < deadline: - with _active_connections_lock: - if _active_connections == 0: - break - time.sleep(0.1) - if SERVER is not None: - SERVER.shutdown() - threading.Thread(target=_drain, daemon=True).start() - -def _upstream_timeout(body, stream): - input_data = body.get("input", "") - n_items = len(input_data) if isinstance(input_data, list) else 1 - has_tools = bool(body.get("tools")) - if stream: - return min((180 if has_tools else 120) + n_items * 2, 300) - return min(60 + n_items * 2, 120) - -def _auto_continue_gemini(handler, flush_event, message_id, model, gen_config, gemini_tools, system_parts, project_id, headers, endpoints, url_suffix, accumulated_text, output_items, message_started): - max_continuations = 5 - for _cont in range(max_continuations): - cont_contents = [ - {"role": "model", "parts": [{"text": accumulated_text[-12000:]}]}, - {"role": "user", "parts": [{"text": "Continue exactly where you left off. Do not repeat anything already written."}]}, - ] - cont_request = {"contents": cont_contents, "generationConfig": dict(gen_config)} - if system_parts: - cont_request["systemInstruction"] = {"parts": system_parts} - if gemini_tools: - cont_request["tools"] = gemini_tools - cont_wrapped = {"project": project_id, "model": model, "request": cont_request} - if OAUTH_PROVIDER == "google-antigravity": - cont_wrapped["requestType"] = "agent" - cont_wrapped["userAgent"] = "antigravity" - cont_wrapped["requestId"] = f"agent-{uuid.uuid4().hex[:12]}" - cont_body = json.dumps(cont_wrapped).encode() - upstream = None - for ep in endpoints: - target = f"{ep}/{url_suffix}" - req = urllib.request.Request(target, data=cont_body, headers=headers) - try: - upstream = urllib.request.urlopen(req, timeout=180) - break - except Exception as e: - print(f"[auto-continue] {ep} failed: {e}", file=sys.stderr) - continue - if not upstream: - break - cont_text = "" - cont_finish = "" - cont_buf = "" - for raw_line in _stream_with_idle_timeout(upstream): - line = raw_line.decode(errors="replace") - if line.startswith("data: "): - cont_buf += line[6:] - continue - if not line.strip() and cont_buf: - try: - chunk = json.loads(cont_buf) - except Exception: - cont_buf = "" - continue - cont_buf = "" - candidates = chunk.get("response", chunk).get("candidates", []) - if not candidates: - continue - cont_finish = candidates[0].get("finishReason", "") - parts = candidates[0].get("content", {}).get("parts", []) - for part in parts: - if part.get("thought"): - continue - if "text" in part and not part.get("functionCall"): - delta = part["text"] - if delta: - cont_text += delta - flush_event("response.output_text.delta", {"type": "response.output_text.delta", "output_index": 0, "content_index": 0, "delta": delta}) - elif part.get("functionCall"): - fc = part["functionCall"] - call_id = f"call_{uuid.uuid4().hex[:24]}" - args_str = json.dumps(fc.get("args", fc.get("arguments", {}))) - output_index = len(output_items) - flush_event("response.output_item.added", {"type": "response.output_item.added", "output_index": output_index, "item": {"type": "function_call", "id": call_id, "call_id": call_id, "name": fc.get("name", ""), "arguments": ""}}) - flush_event("response.function_call_arguments.delta", {"type": "response.function_call_arguments.delta", "output_index": output_index, "item_id": call_id, "delta": args_str}) - flush_event("response.function_call_arguments.done", {"type": "response.function_call_arguments.done", "output_index": output_index, "item_id": call_id, "arguments": args_str}) - output_items.append({"tool": True, "fc": fc, "call_id": call_id}) - accumulated_text += cont_text - print(f"[auto-continue] chunk {len(cont_text)} chars, finish={cont_finish}, total={len(accumulated_text)}", file=sys.stderr) - if cont_finish != "MAX_TOKENS": - break - return accumulated_text - -_ANTIGRAVITY_MAX_CONTENTS = 20 -_ANTIGRAVITY_MAX_TOOL_VERBATIM = 2 -_ANTIGRAVITY_MAX_TOOL_CHARS = 2000 -_ANTIGRAVITY_MAX_OLD_SUMMARY_CHARS = 1200 -_ANTIGRAVITY_SOFT_CHARS = 120000 -_ANTIGRAVITY_HARD_CHARS = 250000 -_ANTIGRAVITY_EMERGENCY_CHARS = 500000 -_ANTIGRAVITY_SIMPLE_WORDS = frozenset({"hi", "hello", "hey", "test", "ping", "thanks", "thank you", "ok", "okay", "yes", "no", "cool", "nice", "good", "great", "done", "go", "stop", "yep", "nope", "sure", "right", "correct", "continue", "cont", "k", "thx", "ty", "np", "lol", "brb", "bye"}) -_ANTIGRAVITY_EDIT_WORDS = frozenset(("change", "fix", "update", "redesign", "rewrite", "modify", "improve", "replace", "edit", "make it", "add", "remove", "delete", "rename", "move", "convert", "create", "build", "implement")) -_ANTIGRAVITY_REFERENCE_WORDS = frozenset(("previous", "file", "error", "again", "that", "this", "it", "same", "last", "above", "earlier", "before", "earlier output", "last error", "previous result", "what was", "show me", "give me")) - -def _antigravity_is_simple_user(text): - if not text: - return True - stripped = text.strip().lower() - if stripped in _ANTIGRAVITY_SIMPLE_WORDS: - return True - if len(stripped) < 30: - words = set(stripped.split()) - if not words.intersection(_ANTIGRAVITY_REFERENCE_WORDS) and not words.intersection(_ANTIGRAVITY_EDIT_WORDS): - return True - return False - -def _antigravity_normalize_context(input_data, model=""): - if not isinstance(input_data, list) or len(input_data) < 2: - return input_data - is_claude_model = "claude" in model.lower() - - latest_user = "" - latest_user_idx = -1 - for i in range(len(input_data) - 1, -1, -1): - item = input_data[i] - if isinstance(item, dict) and item.get("type") == "message" and item.get("role") == "user": - c = item.get("content", "") - if isinstance(c, str): - latest_user = c - elif isinstance(c, list): - latest_user = "\n".join(p.get("text", p.get("input_text", "")) for p in c if isinstance(p, dict)) - latest_user_idx = i - break - - if not latest_user: - return input_data - - is_simple = _antigravity_is_simple_user(latest_user) - - n_raw = len(input_data) - n_tool_outputs = sum(1 for it in input_data if isinstance(it, dict) and it.get("type") == "function_call_output") - n_tool_calls = sum(1 for it in input_data if isinstance(it, dict) and it.get("type") == "function_call") - - auto_reset = (n_raw > 200 or n_tool_outputs > 20) and is_simple - if os.environ.get("ANTIGRAVITY_AUTO_RESET_POLLUTED_CONTEXT", "1") != "1": - auto_reset = False - - has_compaction_summary = any( - isinstance(it, dict) and it.get("type") == "message" and it.get("role") == "user" - and ("Auto-compacted" in str(it.get("content", "")) or "auto-compacted" in str(it.get("content", "")).lower()) - for it in input_data - ) - - if is_simple and auto_reset and not has_compaction_summary: - system_items = [it for it in input_data if isinstance(it, dict) and it.get("type") == "message" and it.get("role") in ("developer", "system")] - user_item = input_data[latest_user_idx] - result = system_items + [user_item] if system_items else [user_item] - print(f"[antigravity-context] raw_items={n_raw} compacted_items={n_raw} final_items={len(result)}", file=sys.stderr) - print(f"[antigravity-context] raw_tool_outputs={n_tool_outputs} kept_tool_outputs=0", file=sys.stderr) - print(f"[antigravity-context] simple_latest_user=true auto_reset={auto_reset} has_compaction={has_compaction_summary}", file=sys.stderr) - return result - - dev_messages = [] - recent_items = [] - tool_outputs = [] - other_items = [] - - for i, item in enumerate(input_data): - if not isinstance(item, dict): - continue - t = item.get("type") - if t == "message" and item.get("role") in ("developer", "system"): - dev_messages.append(item) - elif t == "function_call_output": - tool_outputs.append((i, item)) - elif t in ("function_call",): - other_items.append((i, item)) - elif t == "message": - recent_items.append((i, item)) - - latest_words = set(latest_user.strip().lower().split()) - has_edit_intent = bool(latest_words.intersection(_ANTIGRAVITY_EDIT_WORDS)) - has_ref_intent = bool(latest_words.intersection(_ANTIGRAVITY_REFERENCE_WORDS)) - if is_claude_model: - keep_tools = len(tool_outputs) - else: - keep_tools = 2 if (has_edit_intent or has_ref_intent) else 1 - - if is_claude_model: - kept_tools = tool_outputs - else: - kept_tools = tool_outputs[-keep_tools:] if tool_outputs and (has_edit_intent or has_ref_intent) else [] - - for idx_t, t_item in enumerate(kept_tools): - orig = t_item[1] - out = orig.get("output", "") - if isinstance(out, str) and len(out) > _ANTIGRAVITY_MAX_TOOL_CHARS: - new_item = dict(orig) - new_item["output"] = out[:_ANTIGRAVITY_MAX_TOOL_CHARS] + f"\n... [truncated: kept {_ANTIGRAVITY_MAX_TOOL_CHARS} of {len(out)} chars]" - kept_tools[idx_t] = (t_item[0], new_item) - - n_summarized = len(tool_outputs) - len(kept_tools) - - tail_start = max(0, len(recent_items) - 6) - recent_tail = recent_items[tail_start:] - - deduped_tail = [] - seen_goal_context = False - for idx, msg_item in recent_tail: - content_str = "" - c = msg_item.get("content", "") - if isinstance(c, str): - content_str = c - elif isinstance(c, list): - content_str = " ".join(p.get("text", p.get("input_text", "")) for p in c if isinstance(p, dict)) - if "" in content_str: - if seen_goal_context: - continue - seen_goal_context = True - deduped_tail.append((idx, msg_item)) - recent_tail = deduped_tail if deduped_tail else recent_tail - - tool_call_ids = set() - for _, t_item in kept_tools: - cid = t_item.get("call_id", t_item.get("id", "")) - if cid: - tool_call_ids.add(cid) - - paired_calls = [] - for idx, item in other_items: - cid = item.get("call_id", item.get("id", "")) - if cid in tool_call_ids: - paired_calls.append((idx, item)) - - result = list(dev_messages) - - compaction_summaries = [] - for idx, msg_item in recent_items: - if msg_item is input_data[latest_user_idx]: - continue - c = msg_item.get("content", "") - content_str = c if isinstance(c, str) else " ".join(p.get("text", p.get("input_text", "")) for p in c if isinstance(p, dict)) if isinstance(c, list) else "" - if "Auto-compacted" in content_str or "auto-compacted" in content_str.lower(): - compaction_summaries.append(msg_item) - - if n_summarized > 0: - summary_text = f"[Tool history summary: {n_summarized} older tool outputs omitted. {n_tool_calls} prior function calls were made for file inspection/editing.]" - result.append({"type": "message", "role": "user", "content": [{"type": "input_text", "text": summary_text}]}) - - for _, call_item in paired_calls: - result.append(call_item) - - for _, tool_item in kept_tools: - result.append(tool_item) - - for cs_item in compaction_summaries: - result.append(cs_item) - - for _, msg_item in recent_tail: - if msg_item is not input_data[latest_user_idx]: - result.append(msg_item) - - latest_norm = " ".join(latest_user.strip().split())[:200].lower() - already_present = False - for r in result: - if isinstance(r, dict) and r.get("type") == "message" and r.get("role") == "user": - c = r.get("content", "") - if isinstance(c, str): - rn = " ".join(c.strip().split())[:200].lower() - elif isinstance(c, list): - combined = " ".join(p.get("text", p.get("input_text", "")) for p in c if isinstance(p, dict)) - rn = " ".join(combined.strip().split())[:200].lower() - else: - rn = "" - if rn == latest_norm: - already_present = True - break - - if not already_present: - result.append(input_data[latest_user_idx]) - - total_chars = sum(len(json.dumps(it, ensure_ascii=False)) for it in result) - - if total_chars > _ANTIGRAVITY_EMERGENCY_CHARS: - print(f"[antigravity-context] EMERGENCY: {total_chars} chars exceeds limit, resetting to minimal", file=sys.stderr) - result = list(dev_messages) - if compaction_summaries: - result.extend(compaction_summaries) - result.append(input_data[latest_user_idx]) - total_chars = sum(len(json.dumps(it, ensure_ascii=False)) for it in result) - - while len(result) > _ANTIGRAVITY_MAX_CONTENTS and total_chars > _ANTIGRAVITY_SOFT_CHARS: - for i in range(1, len(result) - 1): - if isinstance(result[i], dict) and result[i].get("type") in ("message", "function_call_output"): - removed = result.pop(i) - total_chars -= len(json.dumps(removed, ensure_ascii=False)) - break - else: - break - - est_tokens = total_chars // 4 - print(f"[antigravity-context] raw_items={n_raw} final_items={len(result)}", file=sys.stderr) - print(f"[antigravity-context] raw_tool_outputs={n_tool_outputs} kept_tool_outputs={len(kept_tools)} summarized_tool_outputs={n_summarized}", file=sys.stderr) - print(f"[antigravity-context] simple_latest_user={is_simple} auto_reset={auto_reset}", file=sys.stderr) - print(f"[antigravity-context] final_chars={total_chars} estimated_tokens={est_tokens}", file=sys.stderr) - - return result - -class Handler(http.server.BaseHTTPRequestHandler): - protocol_version = "HTTP/1.1" - - def do_GET(self): - if self.path in ("/v1/models", "/models"): - self.send_json(200, {"object": "list", "data": MODELS}) - elif self.path in ("/v1/accounts", "/accounts"): - info = {"provider": BACKEND, "oauth_provider": OAUTH_PROVIDER} - if BACKEND in ("codebuff", "freebuff"): - info["accounts"] = _cb_pool.status() - info["total"] = len(_cb_pool._accounts) - elif OAUTH_PROVIDER and OAUTH_PROVIDER.startswith("google"): - pool = _google_antigravity_pool if OAUTH_PROVIDER == "google-antigravity" else _google_cli_pool - info["accounts"] = pool.status() - info["total"] = len(pool._accounts) - elif _api_key_pool: - info["accounts"] = _api_key_pool.status() - info["total"] = len(_api_key_pool._accounts) - else: - info["accounts"] = [] - info["total"] = 0 - self.send_json(200, info) - elif self.path in ("/health", "/v1/health"): - _mem_mb = 0 - try: - if _IS_WINDOWS: - import ctypes - class _PMI(ctypes.Structure): - _fields_ = [("cb", ctypes.c_ulong), ("PageFaultCount", ctypes.c_ulong), - ("PeakWorkingSetSize", ctypes.c_size_t), ("WorkingSetSize", ctypes.c_size_t), - ("QuotaPeakPagedPoolUsage", ctypes.c_size_t), ("QuotaPagedPoolUsage", ctypes.c_size_t), - ("QuotaPeakNonPagedPoolUsage", ctypes.c_size_t), ("QuotaNonPagedPoolUsage", ctypes.c_size_t), - ("PagefileUsage", ctypes.c_size_t), ("PeakPagefileUsage", ctypes.c_size_t)] - _pmi = _PMI() - _pmi.cb = ctypes.sizeof(_PMI) - ctypes.windll.psapi.GetProcessMemoryInfo.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_ulong] - ctypes.windll.psapi.GetProcessMemoryInfo.restype = ctypes.c_int - ctypes.windll.psapi.GetProcessMemoryInfo( - ctypes.windll.kernel32.GetCurrentProcess(), ctypes.byref(_pmi), _pmi.cb) - _mem_mb = _pmi.PeakWorkingSetSize / (1024 * 1024) - else: - import resource as _res - _mem_mb = _res.getrusage(_res.RUSAGE_SELF).ru_maxrss / 1024 - except Exception: - pass - _uptime = time.time() - _START_TIME if '_START_TIME' in dir() else 0 - self.send_json(200, {"ok": True, "backend": BACKEND, - "target_url": TARGET_URL, - "models": [m.get("id") for m in MODELS], - "bgp_routes": len(BGP_ROUTES), - "uptime_s": round(_uptime, 1), - "memory_mb": round(_mem_mb, 1), - "requests_total": _STATS.get("requests", 0)}) - elif self.path == "/admin/reload": - reloaded = _hot_reload_api_key() - key_preview = API_KEY[:8] + "..." if len(API_KEY) > 8 else "(empty)" - self.send_json(200, {"ok": True, "reloaded": reloaded, - "api_key_preview": key_preview, - "config_path": _CONFIG_PATH or "none"}) - elif self.path == "/admin/verify-key": - result = _verify_api_key(API_KEY, TARGET_URL) - key_preview = API_KEY[:8] + "..." if len(API_KEY) > 8 else "(empty)" - result["api_key_preview"] = key_preview - self.send_json(200, result) - else: - self.send_error(404) - - def do_POST(self): - if _shutdown_requested: - return self.send_json(503, {"error": {"type": "proxy_shutting_down", - "message": "Proxy is shutting down"}}) - if self.path.startswith("/admin/cancel/"): - request_id = self.path.rsplit("/", 1)[-1] - if _cancel_request(request_id): - return self.send_json(200, {"ok": True, "cancelled": request_id}) - return self.send_json(404, {"ok": False, "error": "request_not_found"}) - if self.path in ("/v1/responses", "/responses"): - with ConnectionTracker(): - self._handle() - else: - self.send_error(404) - - _logf = None - - def _handle(self): - _hot_reload_api_key() - try: - clen = int(self.headers.get("Content-Length", 0)) - body = json.loads(self.rfile.read(clen)) - 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() - - prev_id = body.get("previous_response_id") - raw_input = body.get("input", "") - input_data = resolve_previous_response(body) - input_data = _compact_input(input_data) - body["input"] = input_data - - 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"[{_sid}] prev_id={prev_id} raw={raw_types} resolved={resolved_types}", file=sys.stderr) - with open(_log_path, "a", encoding="utf-8") as _lf: - _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") - _lf.write(f" stream={body.get('stream')} model={body.get('model')} force_model={FORCE_MODEL}\n") - _lf.write(f" store_keys={list(_response_store.keys())}\n") - if isinstance(input_data, list): - for i, item in enumerate(input_data): - t = item.get("type") - if t == "message": - _lf.write(f" [{i}] message role={item.get('role')} text={str(item.get('content',''))[:120]}\n") - elif t == "function_call": - _lf.write(f" [{i}] function_call call_id={item.get('call_id')} id={item.get('id')} name={item.get('name')} args={item.get('arguments','')[:120]}\n") - elif t == "function_call_output": - _lf.write(f" [{i}] function_call_output id={item.get('id')} output={str(item.get('output',''))[:120]}\n") - else: - _lf.write(f" [{i}] {t}\n") - _lf.flush() - - model = body.get("model", MODELS[0]["id"] if MODELS else "unknown") - if FORCE_MODEL: - model = FORCE_MODEL - body["model"] = FORCE_MODEL - stream = body.get("stream", False) - _desktop_forced_models = {"gpt-5.4-mini", "gpt-5.4", "gpt-5.5", "gpt-5-codex", "gpt-5.3-codex"} - _launcher_model = os.environ.get("CODEX_LAUNCHER_MODEL", "") - if _launcher_model and model in _desktop_forced_models: - print(f"[{_sid}] remap desktop model {model} -> {_launcher_model}", file=sys.stderr) - model = _launcher_model - body["model"] = model - request_id = body.get("request_id") or body.get("id") or uid("req") - if isinstance(input_data, list): - for item in input_data: - if isinstance(item, dict) and item.get("type") == "message" and item.get("role") == "user": - content = str(item.get("content", "")) - for url_m in re.finditer(r"https?://[^\s\]'\"<>]+", content): - _last_user_urls.append(url_m.group(0)) - save_request_snapshot(request_id, body) - _req_t0 = time.time() - wait_start = time.monotonic() - _request_semaphore.acquire() - wait_ms = (time.monotonic() - wait_start) * 1000 - if wait_ms > 100: - print(f"[{_sid}] waited {wait_ms:.0f}ms for upstream slot (concurrency gate)", file=sys.stderr) - try: - with RequestTracker(request_id) as tracker: - if BACKEND == "auto": - self._handle_auto(body, model, stream, tracker) - elif BACKEND == "anthropic": - self._handle_anthropic(body, model, stream, tracker) - elif BACKEND == "command-code": - self._handle_command_code(body, model, stream, tracker) - elif BACKEND in ("codebuff", "freebuff"): - self._handle_codebuff(body, model, stream, tracker) - elif (BACKEND or "").startswith("gemini-oauth"): - self._handle_gemini_oauth(body, model, stream, tracker) - else: - self._handle_openai_compat(body, model, stream, tracker) - update_snapshot_response(request_id, "completed", time.time() - _req_t0) - except Exception as _snap_err: - update_snapshot_response(request_id, "error", time.time() - _req_t0, _snap_err) - raise - finally: - _request_semaphore.release() - - def _handle_openai_compat(self, body, model, stream, tracker=None): - input_data = body.get("input", "") - policy = provider_policy() - - pair_errors = validate_tool_pairs(input_data) - if pair_errors: - print(f"[tool-validator] repairing {len(pair_errors)} orphan tool outputs", file=sys.stderr) - input_data = repair_orphan_tool_outputs(input_data, pair_errors) - body = dict(body) - body["input"] = input_data - - # synthetic tool-results disabled: causes deepseek-v4-pro truncation on opencode.ai - if False and (policy.get("synthetic_tool_results") or _provider_cap(model, "synthetic_tool_results", False)) and isinstance(input_data, list): - input_data, synthesized = synthesize_tool_results_for_chat(input_data) - if synthesized: - print("[provider-adapter] using synthetic tool-result continuation", file=sys.stderr) - body = dict(body) - body["input"] = input_data - - compacted = False - if policy.get("compaction") and isinstance(input_data, list) and "claude" not in model.lower(): - input_data, compacted = _adaptive_compact(input_data, model, policy) - if compacted: - body = dict(body) - body["input"] = input_data - - if PROMPT_ENHANCER and isinstance(input_data, list): - input_data = _apply_prompt_enhancer(input_data) - body = dict(body) - body["input"] = input_data - - crof_limit = _crof_item_limit(model) - _crof_eligible = True - if _crof_eligible and not compacted and isinstance(input_data, list): - _needs_compact = len(input_data) > crof_limit - max_tok = _get_model_max_tokens(model) - est_tok = _estimate_input_tokens(input_data) if max_tok else 0 - if not _needs_compact and max_tok and est_tok > max_tok * 0.8: - _needs_compact = True - if _needs_compact: - _agg = 0 - if max_tok and est_tok > max_tok: - _agg = 1 - print(f"[crof-adaptive] proactive compact: {len(input_data)} items, est={est_tok}tok max={max_tok}tok agg={_agg}", file=sys.stderr) - input_data = _crof_compact_for_retry(input_data, model, aggression=_agg) - body = dict(body) - body["input"] = input_data - - # Strip images for non-vision models - input_data = _strip_images_from_input(input_data, model) - body["input"] = input_data - - messages = oa_input_to_messages(input_data) - messages = _inject_stored_reasoning(messages) - instructions = body.get("instructions", "").strip() - if instructions: - messages.insert(0, {"role": "system", "content": instructions}) - - if BGP_ROUTES: - self._handle_bgp(body, model, stream, messages, input_data) - else: - chat_body = self._build_chat_body(model, messages, body, stream) - target = upstream_target(TARGET_URL, "/chat/completions") - if _api_key_pool: - pool_acct = _api_key_pool.get() - effective_key = pool_acct["token"] if pool_acct else API_KEY - else: - effective_key = _refresh_oauth_token() - fwd = forwarded_headers(self.headers, { - "Content-Type": "application/json", - "Authorization": f"Bearer {effective_key}", - **_openrouter_extra(), - }, browser_ua=True) - 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): - req = urllib.request.Request(target, data=chat_body_b, headers=fwd) - try: - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, stream)) - except urllib.error.HTTPError as e: - err_body = e.read().decode() - if "context_length_exceeded" in err_body and attempt < max_retries: - import re as _re - _tok_m = _re.search(r'~?(\d+)\s*tokens', err_body) - if _tok_m: - _set_model_max_tokens(model, int(_tok_m.group(1))) - print(f"[{self._session_id}] context_length_exceeded (attempt {attempt+1}/{max_retries}), retrying with compaction (agg={attempt})!", file=sys.stderr) - policy = provider_policy() - if isinstance(input_data, list): - est = _estimate_input_tokens(input_data) - print(f"[{self._session_id}] applying compaction to {len(input_data)} items ~{est}tok", file=sys.stderr) - input_data = _crof_compact_for_retry(input_data, model, aggression=attempt) - body = dict(body) - body["input"] = input_data - messages = oa_input_to_messages(_strip_images_from_input(input_data, model)) - messages = _inject_stored_reasoning(messages) - instructions = body.get("instructions", "").strip() - if instructions: - messages.insert(0, {"role": "system", "content": instructions}) - chat_body = self._build_chat_body(model, messages, body, stream) - chat_body_b = json.dumps(chat_body).encode() - continue - if e.code in (429, 502, 503) and attempt < max_retries: - if e.code == 429 and _api_key_pool: - pool_acct = _api_key_pool.get() - if pool_acct: - _api_key_pool.mark_rate_limited(pool_acct, 60) - next_acct = _api_key_pool.get() - if next_acct: - effective_key = next_acct["token"] - fwd["Authorization"] = f"Bearer {effective_key}" - print(f"[multi-account] rotating to key {next_acct['id']}", file=sys.stderr) - 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"[{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"[{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)}}) - except Exception as e: - return self.send_json(500, {"error": {"type": "proxy_error", "message": str(e)}}) - break - self._forward_oa_compat(upstream, stream, model, chat_body, body, input_data, fwd, target, tracker) - - def _build_chat_body(self, model, messages, body, stream): - chat_body = {"model": model, "messages": messages} - for k in ("temperature", "top_p"): - if k in body: - chat_body[k] = body[k] - chat_body["max_tokens"] = max(body.get("max_output_tokens", 0), 64000) - tools = oa_convert_tools(body.get("tools")) - if tools: - chat_body["tools"] = tools - if body.get("tool_choice"): - chat_body["tool_choice"] = body["tool_choice"] - chat_body["stream"] = stream - if not REASONING_ENABLED or REASONING_EFFORT == "none": - chat_body["enable_thinking"] = False - chat_body["reasoning_effort"] = "none" - else: - chat_body["reasoning_effort"] = REASONING_EFFORT - return chat_body - - def _handle_gemini_oauth(self, body, model, stream, tracker=None): - input_data = body.get("input", "") - policy = provider_policy() - original_model = model - - _GEMINI_KEEP_RECENT = 6 - _GEMINI_OLD_LIMIT = 3000 - _GEMINI_RECENT_LIMIT = 20000 - - if isinstance(input_data, list) and len(input_data) > 8: - n_tool_outputs = sum(1 for it in input_data if isinstance(it, dict) and it.get("type") == "function_call_output") - if n_tool_outputs > 2: - tool_indexes = [i for i, it in enumerate(input_data) if isinstance(it, dict) and it.get("type") == "function_call_output"] - recent_set = set(tool_indexes[-_GEMINI_KEEP_RECENT:]) - compacted_data = [] - for i, item in enumerate(input_data): - if isinstance(item, dict) and item.get("type") == "function_call_output": - o = item.get("output", "") - limit = _GEMINI_RECENT_LIMIT if i in recent_set else _GEMINI_OLD_LIMIT - if len(o) > limit: - item = dict(item) - item["output"] = o[:limit] + f"\n... [proxy compacted: kept {limit} of {len(o)} chars]" - compacted_data.append(item) - input_data = compacted_data - body = dict(body) - body["input"] = input_data - print(f"[gemini-compact] {n_tool_outputs} tool outputs, recent={_GEMINI_RECENT_LIMIT} old={_GEMINI_OLD_LIMIT}", file=sys.stderr) - - if OAUTH_PROVIDER == "google-antigravity": - alias_map = { - "Gemini 3.5 Flash (High)": "gemini-3-flash", - "Gemini 3.5 Flash (Medium)": "gemini-3-flash", - "Gemini 3.5 Flash (Low)": "gemini-3.5-flash-low", - "gemini-3.5-flash-high": "gemini-3-flash", - "gemini-3.5-flash-medium": "gemini-3-flash", - "gemini-3.5-flash-low": "gemini-3.5-flash-low", - "gemini-3-flash-preview": "gemini-3-flash", - "gemini-3-flash": "gemini-3-flash", - "antigravity-gemini-3-flash": "gemini-3-flash", - "Gemini 3.1 Pro (High)": "gemini-3.1-pro-low", - "Gemini 3.1 Pro (Low)": "gemini-3.1-pro-low", - "gemini-3.1-pro-high": "gemini-3.1-pro-low", - "gemini-3.1-pro-low": "gemini-3.1-pro-low", - "gemini-3.1-pro-preview": "gemini-3.1-pro-low", - "gemini-3.1-pro": "gemini-3.1-pro-low", - "gemini-3-pro-preview": "gemini-3.1-pro-low", - "gemini-3-pro": "gemini-3.1-pro-low", - "gemini-3-pro-low": "gemini-3.1-pro-low", - "gemini-3-pro-high": "gemini-3.1-pro-low", - "antigravity-gemini-3-pro": "gemini-3.1-pro-low", - "antigravity-gemini-3.1-pro": "gemini-3.1-pro-low", - "Claude Sonnet 4.6 (Thinking)": "claude-sonnet-4-6", - "Claude Sonnet 4.6 Thinking": "claude-sonnet-4-6", - "claude-sonnet-4.6-thinking": "claude-sonnet-4-6", - "antigravity-claude-sonnet-4-6": "claude-sonnet-4-6", - "Claude Opus 4.6 (Thinking)": "claude-opus-4-6-thinking", - "Claude Opus 4.6 Thinking": "claude-opus-4-6-thinking", - "claude-opus-4.6-thinking": "claude-opus-4-6-thinking", - "antigravity-claude-opus-4-6-thinking": "claude-opus-4-6-thinking", - "GPT-OSS 120B (Medium)": "gpt-oss-120b-medium", - "GPT-OSS 120B Medium": "gpt-oss-120b-medium", - "gpt-oss-120b": "gpt-oss-120b-medium", - "gemini-2.5-flash": "gemini-2.5-flash", - "gemini-2.5-pro": "gemini-2.5-pro", - "gemini-2.5-flash-lite": "gemini-2.5-flash-lite", - } - model = alias_map.get(model, model) - if model != original_model: - print(f"[antigravity] model mapped user={original_model} upstream={model}", file=sys.stderr) - - pair_errors = validate_tool_pairs(input_data) - if pair_errors: - input_data = repair_orphan_tool_outputs(input_data, pair_errors) - body = dict(body) - body["input"] = input_data - - compacted = False - if policy.get("compaction") and isinstance(input_data, list) and "claude" not in model.lower(): - input_data, compacted = _adaptive_compact(input_data, model, policy) - if compacted: - body = dict(body) - body["input"] = input_data - - if PROMPT_ENHANCER and isinstance(input_data, list): - input_data = _apply_prompt_enhancer(input_data) - body = dict(body) - body["input"] = input_data - - if OAUTH_PROVIDER == "google-antigravity" and isinstance(input_data, list) and "claude" not in model.lower(): - input_data = _antigravity_normalize_context(input_data, model) - body = dict(body) - body["input"] = input_data - - access_token = _refresh_oauth_token() - 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) - project_id = "" - try: - with open(token_path) as f: - project_id = json.load(f).get("project_id", "") - except Exception: - pass - - contents = [] - system_parts = [] - instructions = body.get("instructions", "").strip() - tool_call_names = {} - - if isinstance(input_data, list): - for item in input_data: - t = item.get("type") - if t == "message": - role = "user" if item.get("role") == "user" else "model" - content = item.get("content", "") - if isinstance(content, list): - parts = [] - for c in content: - ct = c.get("type") - if ct == "input_text": - parts.append({"text": c.get("text", "")}) - elif ct == "text": - parts.append({"text": c.get("text", "")}) - elif ct == "input_image" or ct == "image_url": - iu = c.get("image_url") or c.get("url", {}) - url = iu.get("url", iu) if isinstance(iu, dict) else iu - if isinstance(url, str) and url.startswith("data:"): - mime, _, b64 = url.partition(";base64,") - mime = mime.replace("data:", "") or "image/png" - parts.append({"inlineData": {"mimeType": mime, "data": b64}}) - else: - parts.append({"text": str(url)}) - if parts: - contents.append({"role": role, "parts": parts}) - elif isinstance(content, str): - contents.append({"role": role, "parts": [{"text": content}]}) - elif t == "function_call": - call_id = item.get("call_id") or item.get("id") or f"call_{uuid.uuid4().hex[:24]}" - fname = item.get("name", "") - if call_id and fname: - tool_call_names[call_id] = fname - args = item.get("arguments", "{}") - if isinstance(args, str): - try: - args = json.loads(args) - except Exception: - args = {} - fc_part = {"functionCall": {"name": fname, "args": args, "id": call_id}} - stored_sig = _gemini_get_sig(f"fc:{call_id}") or _gemini_get_sig(f"fc:{fname}") - if stored_sig: - fc_part["thoughtSignature"] = stored_sig - fc_part["thought_signature"] = stored_sig - else: - fc_part["thought_signature"] = "skip_thought_signature_validator" - contents.append({"role": "model", "parts": [fc_part]}) - elif t == "function_call_output": - call_id = item.get("call_id", item.get("id", "")) - output = item.get("output", "") - fname = item.get("name", "") or tool_call_names.get(call_id, "") - try: - output_parsed = json.loads(output) if isinstance(output, str) else output - except Exception: - output_parsed = output - resp_part = {"functionResponse": {"name": fname or "unknown", "response": {"result": output_parsed if isinstance(output_parsed, (dict, list)) else output}}} - if call_id: - resp_part["functionResponse"]["id"] = call_id - contents.append({"role": "user", "parts": [resp_part]}) - - if OAUTH_PROVIDER.startswith("google") and "claude" not in model.lower(): - sanitized = [] - last_user_text = None - last_role = None - for content in contents: - role = content.get("role") - parts = [p for p in content.get("parts", []) if isinstance(p, dict)] - if not parts: - continue - text_key = "\n".join([p.get("text", "") for p in parts if "text" in p]).strip() - if role == "user" and text_key and text_key == last_user_text: - continue - if role == last_role and role in ("user", "model") and sanitized: - sanitized[-1].setdefault("parts", []).extend(parts) - else: - sanitized.append({"role": role, "parts": parts}) - if role == "user" and text_key: - last_user_text = text_key - last_role = role - while sanitized and sanitized[0].get("role") != "user": - sanitized.pop(0) - while sanitized and sanitized[-1].get("role") != "user": - sanitized.pop() - contents = sanitized - - if instructions: - system_parts.append({"text": instructions}) - if OAUTH_PROVIDER == "google-antigravity": - system_parts.append({"text": ( - "You are connected through a Responses API translation proxy. " - "If tools are available and the user's request requires changing files, call the appropriate tool immediately. " - "Do not announce plans, do not say you will list files, browse, fetch, inspect, or start by exploring unless you are emitting the actual tool call in the same response. " - "For file creation requests, use tools to create or modify the file instead of only printing code in chat. " - "If no suitable tool is available, answer directly with the complete result. " - "Never answer only with a plan such as 'I will start by...' or 'I am going to...'." - )}) - - gen_config = {} - mot = body.get("max_output_tokens", 0) - if mot: - gen_config["maxOutputTokens"] = mot - if body.get("temperature") is not None: - gen_config["temperature"] = body["temperature"] - if body.get("top_p") is not None: - gen_config["topP"] = body["top_p"] - - _is_claude_model = "claude" in model.lower() - _is_claude_thinking = _is_claude_model and "thinking" in model.lower() - - if OAUTH_PROVIDER == "google-antigravity" and _is_claude_thinking: - if REASONING_ENABLED and REASONING_EFFORT != "none": - budget = {"low": 8192, "medium": 16384, "high": 32768}.get(REASONING_EFFORT, 16384) - else: - budget = 16384 - gen_config["thinkingConfig"] = { - "include_thoughts": True, - "thinking_budget": budget, - } - current_max = gen_config.get("maxOutputTokens", 0) - if not current_max or current_max <= budget: - gen_config["maxOutputTokens"] = 64000 - print(f"[antigravity-claude] thinking model={model} budget={budget} maxOutputTokens={gen_config.get('maxOutputTokens')}", file=sys.stderr) - elif OAUTH_PROVIDER == "google-antigravity" and _is_claude_model: - if "thinkingConfig" in gen_config: - del gen_config["thinkingConfig"] - elif REASONING_ENABLED and REASONING_EFFORT != "none": - budget = {"low": 2048, "medium": 8192, "high": 24576}.get(REASONING_EFFORT, 8192) - gen_config["thinkingConfig"] = {"includeThoughts": True, "thinkingBudget": budget} - - oa_tools = body.get("tools", []) - gemini_tools = [] - if oa_tools: - func_decls = [] - for tool in oa_tools: - ttype = tool.get("type", "function") - fname = tool.get("name", "") - if ttype == "function": - fn = tool.get("function", tool) - name = fn.get("name", fname) - desc = fn.get("description", "") - params = fn.get("parameters", fn.get("input_schema", {})) - func_decls.append({"name": name, "description": desc, "parameters": params}) - elif fname: - func_decls.append({"name": fname, "description": tool.get("description", ""), "parameters": tool.get("parameters", {"type": "object", "properties": {}})}) - if func_decls: - gemini_tools = [{"functionDeclarations": func_decls}] - - if OAUTH_PROVIDER == "google-antigravity": - contents = _gemini_reattach_sigs(contents) - - if OAUTH_PROVIDER == "google-antigravity": - latest_user = "" - if isinstance(input_data, list): - for item in reversed(input_data): - if item.get("type") == "message" and item.get("role") == "user": - c = item.get("content", "") - if isinstance(c, str): - latest_user = c - elif isinstance(c, list): - latest_user = "\n".join(p.get("text", p.get("input_text", "")) for p in c if isinstance(p, dict)) - break - is_latest_simple = _antigravity_is_simple_user(latest_user) - if not is_latest_simple: - contents.insert(0, {"role": "user", "parts": [{"text": _GEMINI_AGENT_GUARDRAIL}]}) - - if OAUTH_PROVIDER == "google-antigravity": - import hashlib - ag_key = _antigravity_loop_key(self._session_id) - with _ANTIGRAVITY_LOOP_TRACKER_LOCK: - if ag_key not in _ANTIGRAVITY_LOOP_TRACKER: - _ANTIGRAVITY_LOOP_TRACKER[ag_key] = { - "latest_user_hash": None, - "nudge_injected": False, - "latest_user_appended": False, - "tool_calls_for_request": 0, - "repeated_tool": False, - "force_finalize": False, - "last_tool": None, - "last_tool_count": 0, - } - ag_state = _ANTIGRAVITY_LOOP_TRACKER[ag_key] - - latest_user = "" - latest_user_hash = None - if isinstance(input_data, list): - for item in reversed(input_data): - if item.get("type") == "message" and item.get("role") == "user": - c = item.get("content", "") - if isinstance(c, str): - latest_user = c - elif isinstance(c, list): - latest_user = "\n".join(p.get("text", p.get("input_text", "")) for p in c if isinstance(p, dict)) - break - if latest_user: - latest_norm = " ".join(latest_user.strip().split())[:200] - latest_user_hash = hashlib.sha256(latest_norm.encode()).hexdigest()[:16] - if latest_user_hash != ag_state["latest_user_hash"]: - ag_state["latest_user_hash"] = latest_user_hash - ag_state["nudge_injected"] = False - ag_state["latest_user_appended"] = False - ag_state["tool_calls_for_request"] = 0 - ag_state["repeated_tool"] = False - ag_state["force_finalize"] = False - ag_state["last_tool"] = None - ag_state["last_tool_count"] = 0 - - if isinstance(input_data, list): - n_tool_calls = sum(1 for it in input_data if isinstance(it, dict) and it.get("type") == "function_call") - ag_state["tool_calls_for_request"] = n_tool_calls - last_tool_key = None - for item in reversed(input_data): - if isinstance(item, dict) and item.get("type") == "function_call": - fname = item.get("name", "") - args_str = json.dumps(item.get("arguments", {}), sort_keys=True)[:100] - last_tool_key = f"{fname}:{args_str}" - break - if last_tool_key: - if last_tool_key == ag_state["last_tool"]: - ag_state["last_tool_count"] += 1 - if ag_state["last_tool_count"] >= 5: - ag_state["repeated_tool"] = True - ag_state["force_finalize"] = True - else: - ag_state["last_tool"] = last_tool_key - ag_state["last_tool_count"] = 1 - - _EDIT_WORDS = ("change", "fix", "update", "redesign", "rewrite", "modify", "improve", "replace", "edit", "make it", "add", "remove", "delete", "rename", "move", "convert") - latest_lower = "" - if isinstance(input_data, list): - for item in reversed(input_data): - if item.get("type") == "message" and item.get("role") == "user": - c = item.get("content", "") - if isinstance(c, str): latest_lower = c.lower() - elif isinstance(c, list): latest_lower = " ".join(p.get("text", p.get("input_text", "")) for p in c if isinstance(p, dict)).lower() - break - - if ag_state["force_finalize"]: - contents.append({"role": "user", "parts": [{"text": "STOP CALLING TOOLS. APPLY THE FINAL EDIT OR SUMMARIZE WHAT BLOCKED YOU. DO NOT CALL ANY MORE TOOLS. DO NOT PRODUCE ANY MORE PLANNING TEXT. DO NOT PRODUCE ANY MORE EXPLORATORY TOOL CALLS. PRODUCE A FINAL ANSWER OR A CLEAR STATEMENT OF WHAT IS PREVENTING YOU FROM COMPLETING THE TASK."}]}) - elif latest_lower and any(w in latest_lower for w in _EDIT_WORDS) and not ag_state["nudge_injected"] and not ag_state["force_finalize"]: - contents.append({"role": "user", "parts": [{"text": "!!! ABSOLUTELY NO PLANNING - EMIT THE TOOL CALL NOW !!! IMPORTANT: The user is requesting a modification to existing files. You MUST use tools (exec_command, read_files, write, etc.) to make the changes RIGHT NOW. Do NOT just describe what to do — actually CALL THE TOOLS IN THIS RESPONSE. IMMEDIATELY INSPECT THE FILE OR LIST FILES USING exec_command TOOL CALL."}]}) - ag_state["nudge_injected"] = True - print(f"[antigravity] edit-intent detected; injected tool-use nudge (first time for this request)", file=sys.stderr) - else: - if ag_state["nudge_injected"]: - print(f"[antigravity] edit-intent nudge already injected, skipping", file=sys.stderr) - - if latest_user and not ag_state["latest_user_appended"] and not ag_state["force_finalize"]: - latest_norm = " ".join(latest_user.strip().split())[:160] - final_text = "" - if contents: - last = contents[-1] - if last.get("role") == "user": - final_text = " ".join(json.dumps(last.get("parts", []), ensure_ascii=False).split()) - if latest_norm[:120] not in final_text: - print(f"[antigravity] latest user instruction was not final turn; appending (first time for this request)", file=sys.stderr) - contents.append({"role": "user", "parts": [{"text": latest_user}]}) - ag_state["latest_user_appended"] = True - else: - print(f"[antigravity] latest user instruction is final turn", file=sys.stderr) - else: - if ag_state["latest_user_appended"]: - print(f"[antigravity] latest user instruction already appended, skipping", file=sys.stderr) - - print(f"[antigravity-loop] latest_user_hash={latest_user_hash}", file=sys.stderr) - print(f"[antigravity-loop] tool_calls_for_request={ag_state['tool_calls_for_request']}", file=sys.stderr) - print(f"[antigravity-loop] repeated_tool={ag_state['repeated_tool']}", file=sys.stderr) - print(f"[antigravity-loop] nudge_injected={ag_state['nudge_injected']}", file=sys.stderr) - print(f"[antigravity-loop] force_finalize={ag_state['force_finalize']}", file=sys.stderr) - print(f"[{self._session_id}] [antigravity-debug] input_items={len(input_data) if isinstance(input_data, list) else 1} contents={len(contents)} latest={latest_user[:80]!r}", file=sys.stderr) - if contents: - last_c = contents[-1] - print(f"[{self._session_id}] [antigravity-debug] final_role={last_c.get('role')} preview={json.dumps(last_c.get('parts', []), ensure_ascii=False)[:200]}", file=sys.stderr) - - request_body = {"contents": contents} - if system_parts: - request_body["systemInstruction"] = {"parts": system_parts} - if gen_config: - request_body["generationConfig"] = gen_config - if gemini_tools: - request_body["tools"] = gemini_tools - - if OAUTH_PROVIDER == "google-antigravity" and _is_claude_model and gemini_tools: - request_body["toolConfig"] = {"functionCallingConfig": {"mode": "VALIDATED"}} - if _is_claude_thinking: - print(f"[antigravity-claude] applied VALIDATED toolConfig for thinking model", file=sys.stderr) - - wrapped = { - "project": project_id, - "model": model, - "request": request_body, - } - if OAUTH_PROVIDER == "google-antigravity": - wrapped["requestType"] = "agent" - wrapped["userAgent"] = "antigravity" - wrapped["requestId"] = f"agent-{uuid.uuid4().hex[:12]}" - wrapped["request"]["sessionId"] = f"{uuid.uuid4().hex}{int(time.time()*1000)}" - - _allow_staging = os.environ.get("ALLOW_ANTIGRAVITY_STAGING", "0") == "1" - if OAUTH_PROVIDER == "google-antigravity": - _antigravity_endpoints = [ - "https://cloudcode-pa.googleapis.com", - "https://daily-cloudcode-pa.googleapis.com", - ] - if _allow_staging: - _antigravity_endpoints.extend([ - "https://daily-cloudcode-pa.sandbox.googleapis.com", - "https://autopush-cloudcode-pa.sandbox.googleapis.com", - ]) - endpoints = _antigravity_endpoints - else: - endpoints = ["https://cloudcode-pa.googleapis.com"] - action = "streamGenerateContent" if stream else "generateContent" - url_suffix = f"v1internal:{action}?alt=sse" if stream else f"v1internal:{action}" - - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {access_token}", - } - if OAUTH_PROVIDER == "google-antigravity": - version = _ensure_antigravity_version() - import platform as _plat - _os_name = _plat.system().lower() - _os_arch = _plat.machine().lower().replace("x86_64", "x64").replace("aarch64", "arm64") - headers["User-Agent"] = f"antigravity/{version} {_os_name}/{_os_arch}" - headers["X-Client-Name"] = "antigravity" - headers["X-Client-Version"] = _ensure_antigravity_client_version() - headers["x-goog-api-client"] = "gl-node/18.18.2 fire/0.8.6 grpc/1.10.x" - else: - headers["User-Agent"] = "google-api-nodejs-client/9.15.1" - 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() - n_contents = len(contents) - has_tools = bool(gemini_tools) - print(f"[{self._session_id}] model={model} stream={stream} items={len(input_data) if isinstance(input_data, list) else 1} project={project_id} contents={n_contents} tools={has_tools}", file=sys.stderr) - if n_contents > 10: - debug_path = os.path.join(_LOG_DIR, f"gemini-long-ctx-{self._session_id}.json") - try: - with open(debug_path, "w", encoding="utf-8") as dbg: - json.dump({"contents_count": n_contents, "contents_roles": [c.get("role") for c in contents], "has_tools": has_tools, "model": model, "wrapped_size": len(body_b)}, dbg, indent=2) - except Exception: - pass - - if OAUTH_PROVIDER == "google-antigravity": - print(f"[antigravity-endpoint] endpoints={[e.replace('https://','') for e in endpoints]} project={project_id}", file=sys.stderr) - - upstream = None - chosen_ep = None - global _antigravity_preferred_endpoint - - with _antigravity_endpoint_lock: - _pref = _antigravity_preferred_endpoint - - if _pref and _pref in endpoints: - ordered = [_pref] + [e for e in endpoints if e != _pref] - else: - ordered = list(endpoints) - - for ep in ordered: - target = f"{ep}/{url_suffix}" - req = urllib.request.Request(target, data=body_b, headers=headers) - try: - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, stream)) - chosen_ep = ep - with _antigravity_endpoint_lock: - _antigravity_preferred_endpoint = ep - if ep != _pref: - print(f"[{self._session_id}] fallback OK: {ep.replace('https://','')}", file=sys.stderr) - break - except urllib.error.HTTPError as e: - err_body = e.read().decode() - err_class = _classify_antigravity_error(e.code, err_body) - print(f"[{self._session_id}] {ep.replace('https://','')} {e.code} class={err_class}", file=sys.stderr) - if e.code == 400 and OAUTH_PROVIDER.startswith("google"): - try: - debug_path = os.path.join(_LOG_DIR, "gemini-last-400-request.json") - with open(debug_path, "w", encoding="utf-8") as dbg: - json.dump({"endpoint": ep, "model": model, "wrapped": wrapped, "error": err_body}, dbg, indent=2) - print(f"[{self._session_id}] saved 400 debug request to {debug_path}", file=sys.stderr) - except Exception: - pass - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) - if err_class == "auth_permanent": - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) - if err_class in ("quota_exhausted", "rate_limited"): - reset_s = _parse_rate_limit_reset(err_body) - if ep == ordered[-1]: - pool = _google_antigravity_pool if OAUTH_PROVIDER == "google-antigravity" else _google_cli_pool - _, acct = _get_google_account(OAUTH_PROVIDER) - if acct: - cooldown = reset_s if reset_s and reset_s > 10 else 60 - pool.mark_rate_limited(acct, cooldown) - print(f"[{self._session_id}] quota reset in ~{reset_s}s, cooldown={cooldown}s", file=sys.stderr) - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) - print(f"[{self._session_id}] {ep.replace('https://','')} 429, trying next", file=sys.stderr) - with _antigravity_endpoint_lock: - _antigravity_preferred_endpoint = None - continue - if err_class in ("service_disabled", "forbidden", "account_banned", "validation_required"): - if ep == ordered[-1]: - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) - continue - if ep == ordered[-1]: - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) - continue - except Exception as e: - print(f"[{self._session_id}] {ep.replace('https://','')} conn failed: {e}", file=sys.stderr) - if ep == ordered[-1]: - return self.send_json(502, {"error": {"type": "proxy_error", "message": str(e)}}) - continue - - if upstream is None: - return self.send_json(502, {"error": {"type": "proxy_error", "message": "All endpoints failed"}}) - - if stream: - self._forward_gemini_sse(upstream, model, body, input_data, tracker) - else: - self._forward_gemini_json(upstream, model, body, input_data) - - def _forward_gemini_sse(self, upstream, model, body, input_data, tracker=None): - resp_id = f"resp-{uuid.uuid4().hex[:24]}" - created = int(time.time()) - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - - full_text = "" - output_items = [] - current_tool_calls = {} - message_started = False - message_id = f"msg-{uuid.uuid4().hex[:24]}" - - def flush_event(event_type, data): - self.wfile.write(f"event: {event_type}\ndata: {json.dumps(data)}\n\n".encode()) - self.wfile.flush() - - flush_event("response.created", {"type": "response.created", "response": {"id": resp_id, "object": "response", "model": model, "status": "in_progress", "created": created, "output": []}}) - flush_event("response.in_progress", {"type": "response.in_progress", "response": {"id": resp_id}}) - - buf = "" - stream_finished = False - 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 - if stream_finished: - break - line = raw_line.decode(errors="replace") - if line.startswith("data: "): - buf += line[6:] - continue - if not line.strip() and buf: - try: - chunk = json.loads(buf) - except Exception: - buf = "" - continue - buf = "" - - candidates = chunk.get("response", chunk).get("candidates", []) - if not candidates: - if chunk.get("error"): - 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"[{self._session_id}] finish without parts: {candidates[0].get('finishReason')}", file=sys.stderr) - parts = candidates[0].get("content", {}).get("parts", []) - for part in parts: - sig = _extract_gemini_sig(part) - if sig: - if part.get("functionCall"): - fc_id = part["functionCall"].get("id") or part["functionCall"].get("name") - fc_name = part["functionCall"].get("name") - if fc_id: - _gemini_store_sig(f"fc:{fc_id}", sig) - if fc_name: - _gemini_store_sig(f"fc:{fc_name}", sig) - _gemini_store_sig(f"turn:{resp_id}", sig) - if part.get("thought"): - sig_from_thought = _extract_gemini_sig(part) - if sig_from_thought: - _gemini_store_sig(f"turn:{resp_id}", sig_from_thought) - continue - if "text" in part and not part.get("functionCall"): - text_delta = part["text"] - if not text_delta: - continue - full_text += text_delta - if not message_started: - flush_event("response.output_item.added", {"type": "response.output_item.added", "output_index": 0, "item": {"type": "message", "id": message_id, "role": "assistant", "content": []}}) - flush_event("response.content_part.added", {"type": "response.content_part.added", "output_index": 0, "content_index": 0, "part": {"type": "output_text", "text": ""}}) - output_items.append({"text": True}) - message_started = True - flush_event("response.output_text.delta", {"type": "response.output_text.delta", "output_index": 0, "content_index": 0, "delta": text_delta}) - elif part.get("functionCall"): - fc = part["functionCall"] - call_id = f"call_{uuid.uuid4().hex[:24]}" - args_str = json.dumps(fc.get("args", fc.get("arguments", {}))) - output_index = len(output_items) - flush_event("response.output_item.added", {"type": "response.output_item.added", "output_index": output_index, "item": {"type": "function_call", "id": call_id, "call_id": call_id, "name": fc.get("name", ""), "arguments": ""}}) - flush_event("response.function_call_arguments.delta", {"type": "response.function_call_arguments.delta", "output_index": output_index, "item_id": call_id, "delta": args_str}) - flush_event("response.function_call_arguments.done", {"type": "response.function_call_arguments.done", "output_index": output_index, "item_id": call_id, "arguments": args_str}) - current_tool_calls[call_id] = fc - output_items.append({"tool": True}) - last_finish = candidates[0].get("finishReason", "") - if last_finish: - part_kinds = [] - for p in parts: - if "text" in p: part_kinds.append("text") - if "functionCall" in p: part_kinds.append("functionCall") - if _extract_gemini_sig(p): part_kinds.append("thoughtSignature") - print(f"[{self._session_id}] [antigravity] finish={last_finish} parts={part_kinds} tool_calls={len(current_tool_calls)}", file=sys.stderr) - if OAUTH_PROVIDER == "google-antigravity" and last_finish == "MAX_TOKENS" and full_text and not current_tool_calls: - print(f"[{self._session_id}] MAX_TOKENS hit ({len(full_text)} chars), auto-continuing...", file=sys.stderr) - break - stream_finished = True - break - - if OAUTH_PROVIDER.startswith("google") and full_text and not current_tool_calls and last_finish == "MAX_TOKENS" and not stream_finished: - result = _auto_continue_gemini(self, flush_event, message_id, model, gen_config, gemini_tools, system_parts, project_id, headers, endpoints, url_suffix, full_text, output_items, message_started) - if result: - full_text = result - for item in output_items: - if isinstance(item, dict) and item.get("tool") and "fc" in item and "call_id" in item: - current_tool_calls[item["call_id"]] = item["fc"] - - out = [] - if not full_text and not current_tool_calls: - print("[gemini-oauth] WARNING: completed with empty output", file=sys.stderr) - if full_text: - out.append({"type": "message", "id": message_id, "role": "assistant", "content": [{"type": "output_text", "text": full_text}]}) - tool_outputs = [] - for cid, fc in current_tool_calls.items(): - tool_outputs.append({"type": "function_call", "id": cid, "call_id": cid, "name": fc.get("name", ""), "arguments": json.dumps(fc.get("args", fc.get("arguments", {})))}) - out.extend(tool_outputs) - - final_resp = {"id": resp_id, "object": "response", "model": model, "status": "completed", "created": created, "output": out} - if full_text: - flush_event("response.output_text.done", {"type": "response.output_text.done", "output_index": 0, "content_index": 0, "text": full_text}) - flush_event("response.content_part.done", {"type": "response.content_part.done", "output_index": 0, "content_index": 0, "part": {"type": "output_text", "text": full_text}}) - flush_event("response.output_item.done", {"type": "response.output_item.done", "output_index": 0, "item": out[0]}) - for idx, item in enumerate(tool_outputs, start=(1 if full_text else 0)): - flush_event("response.output_item.done", {"type": "response.output_item.done", "output_index": idx, "item": item}) - flush_event("response.completed", {"type": "response.completed", "response": final_resp}) - self.close_connection = True - - with _response_store_lock: - _response_store[resp_id] = final_resp - while len(_response_store) > _MAX_STORED: - _response_store.popitem(last=False) - - def _forward_gemini_json(self, upstream, model, body, input_data): - data = json.loads(upstream.read().decode()) - resp_id = f"resp-{uuid.uuid4().hex[:24]}" - created = int(time.time()) - out = [] - full_text = "" - candidates = data.get("response", data).get("candidates", []) - if candidates: - parts = candidates[0].get("content", {}).get("parts", []) - text_parts = [] - for part in parts: - if part.get("thought"): - continue - if "text" in part and not part.get("functionCall"): - text_parts.append(part["text"]) - elif part.get("functionCall"): - fc = part["functionCall"] - call_id = f"call_{uuid.uuid4().hex[:24]}" - out.append({"type": "function_call", "id": call_id, "call_id": call_id, "name": fc.get("name", ""), "arguments": json.dumps(fc.get("args", fc.get("arguments", {})))}) - if text_parts: - full_text = "".join(text_parts) - out.insert(0, {"type": "message", "id": f"msg-{uuid.uuid4().hex[:24]}", "role": "assistant", "content": [{"type": "output_text", "text": full_text}]}) - resp = {"id": resp_id, "object": "response", "model": model, "status": "completed", "created": created, "output": out} - with _response_store_lock: - _response_store[resp_id] = resp - while len(_response_store) > _MAX_STORED: - _response_store.popitem(last=False) - self.send_json(200, resp) - - def _handle_bgp(self, body, model, stream, messages, input_data): - routes = _sorted_bgp_routes() - routes = [r for r in routes if _bucket_for_route(r).allow()] - if not routes: - return self.send_json(503, {"error": {"type": "bgp_rate_limited", "message": "All routes rate-limited"}}) - errors = [] - for route in routes: - r_model = route.get("model", model) - r_url = route["target_url"].rstrip("/") - r_key = route.get("api_key", "") - r_reasoning = route.get("reasoning_enabled", True) - r_effort = route.get("reasoning_effort", "medium") - r_oauth = route.get("oauth_provider", "") - - chat_body = dict(messages=list(messages)) - chat_body["model"] = r_model - for k in ("temperature", "top_p"): - if k in body: - chat_body[k] = body[k] - chat_body["max_tokens"] = max(body.get("max_output_tokens", 0), 64000) - tools = oa_convert_tools(body.get("tools")) - if tools: - chat_body["tools"] = tools - if body.get("tool_choice"): - chat_body["tool_choice"] = body["tool_choice"] - chat_body["stream"] = stream - if not r_reasoning or r_effort == "none": - chat_body["enable_thinking"] = False - chat_body["reasoning_effort"] = "none" - else: - chat_body["reasoning_effort"] = r_effort - - target = upstream_target(r_url, "/chat/completions") - if r_oauth == "google": - r_key = _refresh_oauth_token_for(r_key, r_oauth) - fwd = forwarded_headers(self.headers, { - "Content-Type": "application/json", - "Authorization": f"Bearer {r_key}", - **_openrouter_extra(), - }, browser_ua=True) - 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"[{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 - except urllib.error.HTTPError as e: - err = e.read().decode() - 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"[{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"[{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"[{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 - _update_route_stats(route, False, time.time() - t0_route, error_type=str(e)) - errors.append(f"{route.get('name','?')}: {e}") - break - except Exception as e: - 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"[{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): - n_items = len(input_data) if isinstance(input_data, list) else 1 - t0 = time.time() - provider = TARGET_URL.split("//")[-1].split("/")[0] - if BGP_ROUTES: - provider = "bgp:" + (BGP_ROUTES[0].get("name", "pool") if BGP_ROUTES else "unknown") - - if stream: - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - if hasattr(self, 'connection') and self.connection: - try: - self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except Exception: - pass - - collected_events = [] - last_resp_id = None - last_output = None - last_status = None - finish_reason = None - has_content = False - has_message = False - has_tool_call = False - - def _observe_event(event): - nonlocal last_resp_id, last_output, last_status, finish_reason, has_content, has_message, has_tool_call - for line in event.strip().split("\n"): - if line.startswith("data: "): - try: - d = json.loads(line[6:]) - if d.get("type") == "response.completed": - last_resp_id = d.get("response", {}).get("id") - last_output = d.get("response", {}).get("output", []) - last_status = d.get("response", {}).get("status") - finish_reason = "length" if last_status == "incomplete" else "stop" - has_tool_call = any(o.get("type") == "function_call" for o in (last_output or [])) - has_message = any(o.get("type") == "message" for o in (last_output or [])) - has_content = has_message or has_tool_call - except Exception: - pass - - try: - reasoning_out = {} - for event in oa_stream_to_sse(upstream, model, body.get("request_id") or body.get("id"), _reasoning_out=reasoning_out): - if tracker and tracker.cancelled.is_set(): - print("[translate-proxy] stream cancelled", file=sys.stderr) - break - collected_events.append(event) - _observe_event(event) - print(f"[{self._session_id}] stream ended: events={len(collected_events)} finish={finish_reason} has_content={has_content} has_message={has_message} has_tool_call={has_tool_call} elapsed={time.time()-t0:.1f}s", file=sys.stderr) - except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError): - print("[translate-proxy] client disconnected during stream", file=sys.stderr) - _crof_record(model, n_items, False) - _log_resp(last_resp_id, "client_disconnect", last_output) - return - except (TimeoutError, OSError, urllib.error.URLError) as e: - print(f"[translate-proxy] upstream error during stream: {type(e).__name__}: {e}", file=sys.stderr) - err_resp_id = body.get("request_id") or body.get("id") or uid("resp") - try: - self.wfile.write(emit("response.failed", {"type": "response.failed", - "response": {"id": err_resp_id, "error": {"type": "upstream_error", - "code": "stream_interrupted", "message": str(e)[:200]}}}).encode()) - self.wfile.flush() - except Exception: - pass - _crof_record(model, n_items, False) - _log_resp(last_resp_id, "upstream_error", last_output) - return - - # Record outcome - success = (finish_reason != "length") - _crof_record(model, n_items, success) - _log_resp(last_resp_id, last_status, last_output) - if last_resp_id and input_data is not None: - store_response(last_resp_id, input_data, last_output) - if reasoning_out.get("text"): - with _last_reasoning_lock: - _last_reasoning_store[last_resp_id or ""] = { - "reasoning": reasoning_out["text"], - "tool_calls": reasoning_out.get("tool_calls", []), - "ts": time.time(), - } - while len(_last_reasoning_store) > _MAX_STORED: - oldest = next(iter(_last_reasoning_store)) - del _last_reasoning_store[oldest] - _record_usage(provider, model, success, time.time() - t0, error_type="length" if not success else None) - - # Auto-learn provider quirks before flushing the bad response to Codex. - if finish_reason == "length" and not has_content and has_function_call_output(input_data): - _set_provider_cap(model, "synthetic_tool_results", True, "incomplete empty response after tool output") - new_input, synthesized = synthesize_tool_results_for_chat(input_data) - if synthesized: - print("[provider-sensor] retrying turn with synthetic tool results", file=sys.stderr) - new_messages = oa_input_to_messages(new_input) - instructions = body.get("instructions", "").strip() - if instructions: - new_messages.insert(0, {"role": "system", "content": instructions}) - new_chat_body = self._build_chat_body(model, new_messages, body, stream) - new_req = urllib.request.Request(target, data=json.dumps(new_chat_body).encode(), headers=fwd) - try: - retry_upstream = urllib.request.urlopen(new_req, timeout=_upstream_timeout(body, True)) - collected_events = [] - last_resp_id = last_output = last_status = None - finish_reason = None - has_content = False - has_message = False - has_tool_call = False - for event in oa_stream_to_sse(retry_upstream, model, body.get("request_id") or body.get("id")): - collected_events.append(event) - _observe_event(event) - input_data = new_input - except Exception as e: - print(f"[provider-sensor] synthetic retry failed: {e}", file=sys.stderr) - - # Auto-retry on finish_reason=length with no content due to too much context. - if finish_reason == "length" and not has_content and isinstance(input_data, list) and len(input_data) > 5: - print(f"[crof-adaptive] RETRY: finish_reason=length with no content, compacting {n_items} items", file=sys.stderr) - new_input = _crof_compact_for_retry(input_data, model) - if len(new_input) < len(input_data): - new_body = dict(body) - new_body["input"] = new_input - new_messages = oa_input_to_messages(new_input) - instructions = body.get("instructions", "").strip() - if instructions: - new_messages.insert(0, {"role": "system", "content": instructions}) - new_chat_body = dict(chat_body) - new_chat_body["messages"] = new_messages - new_req = urllib.request.Request( - target, - data=json.dumps(new_chat_body).encode(), - headers=fwd, - ) - try: - retry_upstream = urllib.request.urlopen(new_req, timeout=_upstream_timeout(body, True)) - collected_events = [] - last_resp_id = last_output = last_status = None - finish_reason = None - has_content = False - has_message = False - has_tool_call = False - for event in oa_stream_to_sse(retry_upstream, model, body.get("request_id") or body.get("id")): - collected_events.append(event) - _observe_event(event) - input_data = new_input - except Exception as e: - print(f"[crof-adaptive] retry failed: {e}", file=sys.stderr) - - # ── Auto-continue for truncated responses ── (cobra PR) - _ac_did_run = False - if stream and collected_events: - _ac_text = "" - _ac_msg_id = _ac_resp_id = None - for _ev in collected_events: - for _ln in _ev.strip().split("\n"): - if not _ln.startswith("data: "): - continue - try: - _d = json.loads(_ln[6:]) - _t = _d.get("type") - if _t == "response.output_text.done": - _ac_text = _d.get("text", "") - elif _t == "response.output_item.added" and _d.get("item",{}).get("type") == "message": - _ac_msg_id = _d.get("item",{}).get("id") - elif _t == "response.completed": - _ac_resp_id = _d.get("response",{}).get("id") - except Exception: - pass - - _ac_tc = reasoning_out.get("tool_calls", []) - _ac_truncated = False - if not _ac_tc and _ac_text: - _ac_stripped = _ac_text.rstrip() - if finish_reason == "length": - _ac_truncated = True - elif len(_ac_stripped) > 10 and _ac_stripped[-1] in "(:,;…": - _ac_truncated = True - - if _ac_truncated and _ac_text: - print(f"[{self._session_id}] auto-continue: truncated (finish={finish_reason}, ends '{_ac_text.rstrip()[-10:]}')", file=sys.stderr) - _ac_did_run = True - _ac_cut = len(collected_events) - for _i, _ev2 in enumerate(collected_events): - if "response.output_text.done" in _ev2: - _ac_cut = _i - break - collected_events = collected_events[:_ac_cut] - - _ac_accumulated = _ac_text - _ac_max = 3 - for _ac_attempt in range(_ac_max): - try: - _ac_cont_msgs = list(chat_body.get("messages", [])) - _ac_cont_msgs.append({"role": "assistant", "content": _ac_accumulated}) - _ac_cont_msgs.append({"role": "user", "content": "Continue exactly where you left off. Do not repeat anything already written."}) - _ac_cont_body = dict(chat_body) - _ac_cont_body["messages"] = _ac_cont_msgs - _ac_cont_body["stream"] = False - _ac_cont_req = urllib.request.Request(target, data=json.dumps(_ac_cont_body).encode(), headers=fwd) - _ac_cont_resp = json.loads(urllib.request.urlopen(_ac_cont_req, timeout=120).read()) - _ac_choices = _ac_cont_resp.get("choices", []) - if _ac_choices: - _ac_chunk = _ac_choices[0].get("message",{}).get("content","") - if not _ac_chunk: - _ac_chunk = _ac_choices[0].get("delta",{}).get("content","") - _ac_finish = _ac_choices[0].get("finish_reason") - if _ac_chunk: - _ac_accumulated += _ac_chunk - collected_events.append(emit("response.output_text.delta", { - "type": "response.output_text.delta", - "delta": _ac_chunk, "item_id": _ac_msg_id, "content_index": 0})) - if _ac_finish != "length": - break - _ac_text = _ac_accumulated - except Exception as _ac_e: - print(f"[{self._session_id}] auto-continue attempt {_ac_attempt+1} failed: {_ac_e}", file=sys.stderr) - break - - if _ac_msg_id: - collected_events.append(emit("response.output_text.done", { - "type": "response.output_text.done", - "text": _ac_accumulated, "item_id": _ac_msg_id, "content_index": 0})) - collected_events.append(emit("response.content_part.done", { - "type": "response.content_part.done", - "part": {"type": "output_text", "text": _ac_accumulated, "annotations": []}, "item_id": _ac_msg_id})) - collected_events.append(emit("response.output_item.done", { - "type": "response.output_item.done", - "item": {"type": "message", "id": _ac_msg_id, "role": "assistant", "status": "completed", - "content": [{"type": "output_text", "text": _ac_accumulated, "annotations": []}]}})) - if _ac_resp_id: - collected_events.append(emit("response.completed", { - "type": "response.completed", - "response": {"id": _ac_resp_id, "object": "response", "model": model, - "status": "completed", "created": int(time.time()), - "output": [{"type": "message", "id": _ac_msg_id, "role": "assistant", - "status": "completed", - "content": [{"type": "output_text", "text": _ac_accumulated, "annotations": []}]}]}})) - has_content = True - finish_reason = "stop" - print(f"[{self._session_id}] auto-continue done: {len(_ac_text)} -> {len(_ac_accumulated)} chars", file=sys.stderr) - - # Smart continuation: loop with escalating nudges when model stops text-only mid-task. - # Skip if auto-continue already handled the response. - if not _ac_did_run: - _smart_max = 2 - _smart_attempt = 0 - while _smart_attempt < _smart_max: - _has_tool_calls_in_output = any(o.get("type") == "function_call" for o in (last_output or [])) - last_text = "" - for o in (last_output or []): - if o.get("type") == "message": - for c in (o.get("content") or []): - if isinstance(c, dict) and c.get("type") == "output_text": - last_text += c.get("text", "") - _looks_like_tools = _text_looks_like_tool_calls(last_text) - _has_prior_tool_ctx = has_function_call_output(input_data) - if not (finish_reason == "stop" and has_content and not _has_tool_calls_in_output - and isinstance(input_data, list) and len(input_data) >= 3 - and (_has_prior_tool_ctx or _looks_like_tools)): - break - _smart_attempt += 1 - _nudges = [ - "Continue with the task using tool calls. Do NOT describe what to do — call the appropriate functions.", - "You MUST use tool calls to complete the task. Read files, run commands, and make changes using tools. Do NOT output XML tool calls as text.", - ] - nudge_text = _nudges[min(_smart_attempt - 1, len(_nudges) - 1)] - # Try extracting XML tool calls from text as fallback before nudging - xml_fc = _extract_xml_tool_calls(last_text) - if xml_fc: - print(f"[{self._session_id}] [smart-continue] extracted {len(xml_fc)} XML tool calls from text, injecting and retrying", file=sys.stderr) - fake_input = list(input_data) - for xfc in xml_fc: - fake_input.append({"type": "function_call", "id": uid("fcx"), "call_id": uid("fcx"), - "name": xfc["name"], "arguments": xfc["args"], "status": "completed"}) - fake_messages = oa_input_to_messages(fake_input) - instructions = body.get("instructions", "").strip() - if instructions: - fake_messages.insert(0, {"role": "system", "content": instructions}) - fake_chat_body = self._build_chat_body(model, fake_messages, body, stream) - fake_req = urllib.request.Request(target, data=json.dumps(fake_chat_body).encode(), headers=fwd) - try: - retry_upstream = urllib.request.urlopen(fake_req, timeout=_upstream_timeout(body, True)) - collected_events = [] - last_resp_id = last_output = last_status = None - finish_reason = None - has_content = False - has_message = False - has_tool_call = False - for event in oa_stream_to_sse(retry_upstream, model, body.get("request_id") or body.get("id")): - collected_events.append(event) - _observe_event(event) - input_data = fake_input - continue - except Exception as e: - print(f"[{self._session_id}] [smart-continue] XML injection retry failed: {e}", file=sys.stderr) - break - _nudge_msg = {"role": "user", "content": nudge_text} - nudge_messages = oa_input_to_messages(_strip_images_from_input(input_data, model)) + [_nudge_msg] - instructions = body.get("instructions", "").strip() - if instructions: - nudge_messages.insert(0, {"role": "system", "content": instructions}) - nudge_chat_body = self._build_chat_body(model, nudge_messages, body, stream) - nudge_req = urllib.request.Request(target, data=json.dumps(nudge_chat_body).encode(), headers=fwd) - print(f"[{self._session_id}] [smart-continue] attempt {_smart_attempt}/{_smart_max}: model stopped mid-task (prior_ctx={_has_prior_tool_ctx} text_tools={_looks_like_tools}), nudging", file=sys.stderr) - try: - retry_upstream = urllib.request.urlopen(nudge_req, timeout=_upstream_timeout(body, True)) - collected_events = [] - last_resp_id = last_output = last_status = None - finish_reason = None - has_content = False - has_message = False - has_tool_call = False - for event in oa_stream_to_sse(retry_upstream, model, body.get("request_id") or body.get("id")): - collected_events.append(event) - _observe_event(event) - except Exception as e: - print(f"[{self._session_id}] [smart-continue] nudge attempt {_smart_attempt} failed: {e}", file=sys.stderr) - break - - self.stream_buffered_events(collected_events) - else: - result = oa_resp_to_responses(json.loads(upstream.read()), model) - success = result.get("status") != "incomplete" - _crof_record(model, n_items, success) - self.send_json(200, result) - rid = result.get("id") - _log_resp(rid, result.get("status"), result.get("output", [])) - if rid and input_data is not None: - store_response(rid, input_data, result.get("output", [])) - _record_usage(provider, model, success, time.time() - t0) - - def _forward_oa_compat_retry(self, req, model, chat_body, body, input_data, tracker=None): - try: - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, True)) - except Exception as e: - print(f"[crof-adaptive] retry failed: {e}", file=sys.stderr) - return - - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - if hasattr(self, 'connection') and self.connection: - try: - self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except Exception: - pass - - last_resp_id = None - last_output = None - last_status = None - try: - def on_event(event): - nonlocal last_resp_id, last_output, last_status - if tracker and tracker.cancelled.is_set(): - print("[translate-proxy] retry stream cancelled", file=sys.stderr) - return False - for line in event.strip().split("\n"): - if line.startswith("data: "): - try: - d = json.loads(line[6:]) - if d.get("type") == "response.completed": - last_resp_id = d.get("response", {}).get("id") - last_output = d.get("response", {}).get("output", []) - last_status = d.get("response", {}).get("status") - except: pass - return True - self.stream_buffered_events(oa_stream_to_sse(upstream, model, body.get("request_id") or body.get("id")), on_event=on_event) - except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError): - print("[translate-proxy] client disconnected during retry stream", file=sys.stderr) - - n_items = len(input_data) if isinstance(input_data, list) else 1 - _crof_record(model, n_items, last_status == "completed") - _log_resp(last_resp_id, last_status or "retry_disconnect", last_output) - if last_resp_id and input_data is not None: - store_response(last_resp_id, input_data, last_output) - - def _handle_anthropic(self, body, model, stream, tracker=None): - input_data = body.get("input", "") - an_body = {"model": model, "messages": an_input_to_messages(input_data), - "max_tokens": body.get("max_output_tokens", 8192)} - instructions = body.get("instructions", "").strip() - if instructions: - an_body["system"] = [{"type": "text", "text": instructions, - "cache_control": {"type": "ephemeral"}}] - for k in ("temperature", "top_p"): - if k in body: - an_body[k] = body[k] - tools = an_convert_tools(body.get("tools")) - if tools: - an_body["tools"] = tools - if body.get("tool_choice"): - tc = body["tool_choice"] - if isinstance(tc, str): - an_body["tool_choice"] = {"type": tc} - elif isinstance(tc, dict): - an_body["tool_choice"] = tc - an_body["stream"] = stream - - target = upstream_target(TARGET_URL, "/messages") - req = urllib.request.Request( - target, - data=json.dumps(an_body).encode(), - headers=forwarded_headers(self.headers, { - "Content-Type": "application/json", - "x-api-key": API_KEY, - "anthropic-version": "2023-06-01", - **_openrouter_extra(), - }), - ) - self._forward(req, stream, model, - lambda r: an_resp_to_responses(json.loads(r.read()), model), - lambda s: an_stream_to_sse(s, model, body.get("request_id") or body.get("id")), - input_data=body.get("input", ""), tracker=tracker) - - def _handle_command_code(self, body, model, stream, tracker=None): - """[ALL FIXES IN ONE] CommandCode /alpha/generate adapter. - - FIX 1: Uses cc_input_to_messages (string content only, no content blocks) - FIX 2: Always sends x-command-code-version header (fallback "0.26.8") - FIX 3: No stale schema cache — cleared, 24h TTL - FIX 4: Streaming path wrapped in try/except → sends response.completed(status="failed") on crash - FIX 5: Response parser (_parse_commandcode_text_tool_calls) now extracts raw JSON tool calls - FIX 6: Arguments no longer double-wrapped (three-tier parser in _extract_args) - FIX 7: _extract_field handles escaped values (\") correctly - FIX 8: sandbox_permissions normalized to valid variants only - REVERTED: Removed adaptive probing system (caused format mismatch). - Uses conservative cc_input_to_messages format exclusively. - ErrorAnalyzer learning on retries (not proactive probes). - """ - input_data = body.get("input", "") - instructions = body.get("instructions", "").strip() - - schema = _load_schema(model=model) - - thread_id = body.get("request_id") or body.get("id") or "" - try: - uuid.UUID(thread_id) - except (ValueError, AttributeError): - thread_id = str(uuid.uuid4()) - - # Build auth headers - auth_val = f"{schema.auth_scheme}{API_KEY}" if schema.auth_scheme else API_KEY - headers_extra = { - "Content-Type": "application/json", - "Accept": "text/event-stream, application/json", - } - if schema.auth_header: - headers_extra[schema.auth_header] = auth_val - else: - headers_extra["Authorization"] = f"Bearer {API_KEY}" - headers_extra["x-command-code-version"] = CC_VERSION or "0.26.8" - - pm = schema.param_names - tp = schema.field_names.get("tools_param", "tools") - target = upstream_target(TARGET_URL, "/alpha/generate") - - # ── MAIN REQUEST WITH RETRY ── - max_retries = 2 - for attempt in range(max_retries + 1): - cc_msgs = cc_input_to_messages(input_data, instructions, schema) - cc_body = { - "config": _cc_config(), - "memory": "", "taste": "", "skills": "", - "params": { - "stream": True, - pm.get("max_tokens", "max_tokens"): body.get("max_output_tokens", 64000), - pm.get("temperature", "temperature"): body.get("temperature", 0.3), - "messages": cc_msgs, - "model": model, - tp: [], - }, - "threadId": thread_id, - } - - fwd = forwarded_headers(self.headers, {**headers_extra, **_openrouter_extra()}, browser_ua=True) - 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(), - headers=fwd, - ) - - try: - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, True)) - break - except urllib.error.HTTPError as e: - err = e.read().decode() - if attempt < max_retries: - hints = ErrorAnalyzer.analyze(err, schema) - if hints: - print(f"[{self._session_id}] error analysis: {hints}", file=sys.stderr) - ErrorAnalyzer.merge_into_schema(hints, schema) - _save_schema(schema, model=model) - continue - if e.code in (429, 502, 503): - time.sleep(min(2 ** (attempt + 1), 10)) - continue - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err)}}) - except Exception as e: - if attempt < max_retries: - time.sleep(1) - continue - return self.send_json(500, {"error": {"type": "proxy_error", "message": str(e)}}) - - _save_schema(schema, model=model) - - if stream: - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - if hasattr(self, 'connection') and self.connection: - try: - self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except Exception: - pass - last_resp_id = None - last_output = None - def on_event(event): - nonlocal last_resp_id, last_output - if tracker and tracker.cancelled.is_set(): - print("[command-code] stream cancelled", file=sys.stderr) - return False - for line in event.strip().split("\n"): - if line.startswith("data: "): - try: - d = json.loads(line[6:]) - if d.get("type") == "response.completed": - last_resp_id = d.get("response", {}).get("id") - last_output = d.get("response", {}).get("output", []) - except: pass - return True - 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"[{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"), - "object": "response", "model": model, "status": "failed", - "created": int(time.time()), "output": [], - "usage": {"input_tokens": 0, "output_tokens": 0, "total_tokens": 0, - "input_tokens_details": {"cached_tokens": 0}}}}) - self.wfile.write(err_event.encode()) - self.wfile.flush() - except Exception: - pass - if last_resp_id: - store_response(last_resp_id, body.get("input", ""), last_output) - else: - raw = upstream.read().decode() - result = cc_resp_to_responses(raw, model) - self.send_json(200, result) - rid = result.get("id") - if rid: - store_response(rid, body.get("input", ""), result.get("output", [])) - - def _handle_codebuff(self, body, model, stream, tracker=None): - agent_id = _CODEBUFF_AGENT_MAP.get(model) - if not agent_id: - matched = None - for m in _CODEBUFF_AGENT_MAP: - if model.lower().replace("/", "").replace("-", "") in m.lower().replace("/", "").replace("-", ""): - matched = m - break - if matched: - agent_id = _CODEBUFF_AGENT_MAP[matched] - model = matched - else: - fallback_model = "deepseek/deepseek-v4-flash" - agent_id = _CODEBUFF_AGENT_MAP.get(fallback_model, "base2-free-deepseek-flash") - print(f"[codebuff] unknown model '{model}', falling back to {fallback_model}", file=sys.stderr) - model = fallback_model - - _cb_pool.load_accounts() - pool_status = _cb_pool.status() - n_accounts = len(pool_status) - if n_accounts == 0: - return self.send_json(401, {"error": {"type": "auth_error", - "message": "No codebuff credentials found. Add accounts to ~/.config/manicode/credentials.json"}}) - - last_err = None - for attempt in range(n_accounts): - token, acct = _get_codebuff_account() - if not token: - return self.send_json(401, {"error": {"type": "auth_error", - "message": "No codebuff credentials found. All accounts exhausted."}}) - - acct_id = acct.get("id", "?") if acct else "?" - if attempt > 0: - print(f"[codebuff] rotation attempt {attempt+1}/{n_accounts}, trying account {acct_id}", file=sys.stderr) - - run_id, run_err = _codebuff_start_run(token, agent_id) - if not run_id: - if run_err and run_err[0] == "rate_limit_error": - retry_s = run_err[2] - _cb_pool.mark_rate_limited(acct, retry_s) - last_err = ("rate_limit_error", run_err[1], f"Account {acct_id} rate-limited by Codebuff: {run_err[3]}") - else: - _cb_pool.mark_rate_limited(acct, 60) - last_err = ("upstream_error", run_err[1] if run_err else 502, - f"Failed to start agent run for {acct_id}: {run_err[3] if run_err else 'unknown error'}") - continue - - try: - instance_id = _codebuff_get_session(token, model) - except RateLimitError as rle: - retry_s = rle.retry_seconds - fb_msg = rle.message - mins = int(retry_s // 60) - user_msg = fb_msg if fb_msg else f"Daily session limit reached. Resets in {mins}m." - print(f"[codebuff] session 429 for {acct_id}, retry after {retry_s:.0f}s", file=sys.stderr) - _cb_pool.mark_rate_limited(acct, retry_s) - _codebuff_finish_run(token, run_id, "completed") - last_err = ("rate_limit_error", 429, user_msg) - continue - - input_data = body.get("input", "") - instructions = body.get("instructions", "").strip() - messages = _cb_input_to_messages(input_data, instructions) - messages = _ds_rebuild_tool_history(messages) - - metadata = { - "run_id": run_id, - "cost_mode": "free", - "client_id": "".join(secrets.choice(string.digits + string.ascii_lowercase) for _ in range(13)), - } - if instance_id: - metadata["freebuff_instance_id"] = instance_id - - chat_body = { - "model": model, - "messages": messages, - "stream": stream, - "max_tokens": max(body.get("max_output_tokens", 0), 64000), - "codebuff_metadata": metadata, - } - for k in ("temperature", "top_p"): - if k in body: - chat_body[k] = body[k] - tools = oa_convert_tools(body.get("tools")) - if tools: - chat_body["tools"] = tools - if body.get("tool_choice"): - chat_body["tool_choice"] = body["tool_choice"] - - target = f"{_CODEBUFF_API_URL}/api/v1/chat/completions" - headers = { - "Content-Type": "application/json", - "Authorization": f"Bearer {token}", - "User-Agent": "ai-sdk/openai-compatible/1.0.25/codebuff", - "x-codebuff-model": model, - } - if instance_id: - headers["x-codebuff-instance-id"] = instance_id - - print(f"[{self._session_id}] [codebuff] POST {target} model={model} stream={stream} run={run_id} acct={acct_id}", file=sys.stderr) - chat_body_b = json.dumps(chat_body).encode() - - try: - req = urllib.request.Request(target, data=chat_body_b, headers=headers) - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, stream)) - except urllib.error.HTTPError as e: - err_body = e.read().decode()[:1000] - _codebuff_finish_run(token, run_id, "failed") - if e.code in (429, 426): - reset_ms = 0 - fb_msg = "" - try: - err_json = json.loads(err_body) - reset_ms = err_json.get("retryAfterMs", 0) - fb_msg = err_json.get("message", err_json.get("error", "")) - if isinstance(fb_msg, dict): - fb_msg = fb_msg.get("message", "") - except Exception: - pass - duration = max(reset_ms / 1000, 120) if reset_ms else 120 - mins = int(duration // 60) - if not fb_msg: - fb_msg = _sanitize_err_body(err_body) - user_msg = f"{fb_msg} (resets in {mins}m)" if fb_msg else f"Rate limited. Resets in {mins}m." - _cb_pool.mark_rate_limited(acct, duration) - last_err = ("rate_limit_error", e.code, user_msg) - print(f"[codebuff] account {acct_id} got HTTP {e.code}, rotating", file=sys.stderr) - continue - if _is_reasoning_content_error(err_body): - print(f"[codebuff] reasoning_content error, retrying with thinking disabled", file=sys.stderr) - result = self._cb_retry_thinking_disabled(body, model, token, agent_id, stream, tracker, input_data, instructions, err_body, acct) - return result - print(f"[codebuff] HTTP {e.code}: {err_body[:300]}", file=sys.stderr) - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) - except Exception as e: - _codebuff_finish_run(token, run_id, "failed") - return self.send_json(502, {"error": {"type": "proxy_error", "message": str(e)}}) - - t0 = time.time() - try: - if stream: - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - if hasattr(self, 'connection') and self.connection: - try: - self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except Exception: - pass - - last_resp_id = [None] - last_output = [None] - last_status = [None] - finish_reason = [None] - reasoning_out = {} - - def _on_fb_event(event): - if tracker and tracker.cancelled.is_set(): - return False - for line in event.strip().split("\n"): - if line.startswith("data: "): - try: - d = json.loads(line[6:]) - if d.get("type") == "response.completed": - last_resp_id[0] = d.get("response", {}).get("id") - last_output[0] = d.get("response", {}).get("output", []) - last_status[0] = d.get("response", {}).get("status") - finish_reason[0] = "length" if last_status[0] == "incomplete" else "stop" - except Exception: - pass - return None - - try: - self.stream_buffered_events( - oa_stream_to_sse(upstream, model, body.get("request_id") or body.get("id"), - _reasoning_out=reasoning_out), - on_event=_on_fb_event) - except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError): - print(f"[{self._session_id}] [codebuff] client disconnected", file=sys.stderr) - return - - success = finish_reason[0] != "length" - _record_usage("codebuff", model, success, time.time() - t0) - if last_resp_id[0] and input_data is not None: - store_response(last_resp_id[0], input_data, last_output[0]) - if last_resp_id[0] and reasoning_out.get("text") or reasoning_out.get("tool_calls"): - asm = {"role": "assistant", "content": reasoning_out.get("text", "") or ""} - if reasoning_out.get("tool_calls"): - asm["tool_calls"] = reasoning_out["tool_calls"] - if reasoning_out.get("text"): - asm["reasoning_content"] = reasoning_out["text"] - _ds_store_assistant(last_resp_id[0], asm) - print(f"[{self._session_id}] [codebuff] stream done status={last_status[0]} in {time.time()-t0:.1f}s acct={acct_id}", file=sys.stderr) - else: - raw = upstream.read().decode() - chat_resp = json.loads(raw) - result = oa_resp_to_responses(chat_resp, model) - self.send_json(200, result) - rid = result.get("id") - if rid: - store_response(rid, input_data, result.get("output", [])) - print(f"[{self._session_id}] [codebuff] non-stream done in {time.time()-t0:.1f}s acct={acct_id}", file=sys.stderr) - finally: - _codebuff_finish_run(token, run_id, "completed") - return - - if last_err: - msg = last_err[2] - resp_id = f"resp_{uuid.uuid4().hex[:24]}" - result = { - "id": resp_id, - "object": "response", - "created_at": int(time.time()), - "model": model, - "status": "completed", - "output": [{ - "id": f"msg_{uuid.uuid4().hex[:24]}", - "type": "message", - "role": "assistant", - "content": [{ - "type": "output_text", - "text": msg, - "annotations": [], - }], - "status": "completed", - }], - "usage": {"input_tokens": 0, "output_tokens": 0, "total_tokens": 0}, - } - return self.send_json(200, result) - - def _cb_retry_thinking_disabled(self, body, model, token, agent_id, stream, tracker, input_data, instructions, original_error, acct=None): - run_id, run_err = _codebuff_start_run(token, agent_id) - if not run_id: - msg = run_err[3] if run_err else "unknown error" - return self.send_json(run_err[1] if run_err else 502, {"error": {"type": run_err[0] if run_err else "upstream_error", - "message": f"Failed to start agent run for retry: {msg}"}}) - instance_id = _codebuff_get_session(token, model) - messages = _cb_input_to_messages(input_data, instructions) - _codebuff_hard_disable_reasoning(messages) - metadata = {"run_id": run_id, "cost_mode": "free", "client_id": secrets.token_hex(7)[:13]} - if instance_id: - metadata["freebuff_instance_id"] = instance_id - chat_body = { - "model": model, "messages": messages, "stream": stream, - "max_tokens": max(body.get("max_output_tokens", 0), 64000), - "thinking": {"type": "disabled"}, - "codebuff_metadata": metadata, - } - for k in ("temperature", "top_p"): - if k in body: - chat_body[k] = body[k] - tools = oa_convert_tools(body.get("tools")) - if tools: - chat_body["tools"] = tools - if body.get("tool_choice"): - chat_body["tool_choice"] = body["tool_choice"] - target = f"{_CODEBUFF_API_URL}/api/v1/chat/completions" - headers = {"Content-Type": "application/json", "Authorization": f"Bearer {token}", "User-Agent": "ai-sdk/openai-compatible/1.0.25/codebuff", "x-codebuff-model": model} - if instance_id: - headers["x-codebuff-instance-id"] = instance_id - print(f"[codebuff] retry POST {target} model={model} stream={stream} run={run_id} (thinking disabled via DeepSeek native)", file=sys.stderr) - try: - req = urllib.request.Request(target, data=json.dumps(chat_body).encode(), headers=headers) - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, stream)) - except urllib.error.HTTPError as e: - err_body = e.read().decode()[:500] - _codebuff_finish_run(token, run_id, "failed") - print(f"[codebuff] thinking-disabled retry failed: HTTP {e.code}: {err_body[:300]}", file=sys.stderr) - return self.send_json(e.code, {"error": {"type": "codebuff_deepseek_thinking_error", - "message": "Codebuff/DeepSeek V4 requires reasoning_content round-trip for tool-call sessions. Use Command Code provider for this model instead.", "upstream_error": _sanitize_err_body(err_body)}}) - except Exception as e: - _codebuff_finish_run(token, run_id, "failed") - return self.send_json(502, {"error": {"type": "proxy_error", "message": str(e)}}) - t0 = time.time() - try: - if stream: - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - if hasattr(self, 'connection') and self.connection: - try: - self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except Exception: - pass - last_resp_id = [None] - last_output = [None] - last_status = [None] - finish_reason = [None] - reasoning_out = {} - def _on_fb_retry_event(event): - if tracker and tracker.cancelled.is_set(): - return False - for line in event.strip().split("\n"): - if line.startswith("data: "): - try: - d = json.loads(line[6:]) - if d.get("type") == "response.completed": - last_resp_id[0] = d.get("response", {}).get("id") - last_output[0] = d.get("response", {}).get("output", []) - last_status[0] = d.get("response", {}).get("status") - finish_reason[0] = "length" if last_status[0] == "incomplete" else "stop" - except Exception: - pass - return None - try: - self.stream_buffered_events( - oa_stream_to_sse(upstream, model, body.get("request_id") or body.get("id"), - _reasoning_out=reasoning_out), - on_event=_on_fb_retry_event) - except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError): - return - success = finish_reason[0] != "length" - _record_usage("codebuff", model, success, time.time() - t0) - if last_resp_id[0] and input_data is not None: - store_response(last_resp_id[0], input_data, last_output[0]) - if last_resp_id[0] and reasoning_out.get("text") or reasoning_out.get("tool_calls"): - asm = {"role": "assistant", "content": reasoning_out.get("text", "") or ""} - if reasoning_out.get("tool_calls"): - asm["tool_calls"] = reasoning_out["tool_calls"] - if reasoning_out.get("text"): - asm["reasoning_content"] = reasoning_out["text"] - _ds_store_assistant(last_resp_id[0], asm) - print(f"[{self._session_id}] [codebuff] retry stream done status={last_status[0]} in {time.time()-t0:.1f}s", file=sys.stderr) - else: - raw = upstream.read().decode() - chat_resp = json.loads(raw) - result = oa_resp_to_responses(chat_resp, model) - self.send_json(200, result) - rid = result.get("id") - if rid: - store_response(rid, input_data, result.get("output", [])) - print(f"[{self._session_id}] [codebuff] retry non-stream done in {time.time()-t0:.1f}s", file=sys.stderr) - finally: - _codebuff_finish_run(token, run_id, "completed") - - def _handle_auto(self, body, model, stream, tracker=None): - """Auto-sensing backend: probe schema, adapt, retry on errors. - Uses hostname heuristics as initial guess, then learns from errors - and caches the learned schema for subsequent requests. - """ - input_data = body.get("input", "") - instructions = body.get("instructions", "").strip() - - schema = _load_schema(model=model) - fresh = not schema.hints().get("_updated") - host = urllib.parse.urlparse(TARGET_URL).netloc.lower() - - def _detect_style(): - cc = schema.cc_body_wrap or "commandcode" in host or "command-code" in host - anth = schema.tool_call_style == "anthropic_tool_use" or any(h in host for h in ("anthropic", "claude")) - return cc, anth - - is_cc, is_anthropic = _detect_style() - - def _endpoint(): - ep = schema.field_names.get("endpoint_path", "") - if ep: - return ep - if is_cc: - return "/alpha/generate" - if is_anthropic: - return "/messages" - return "/chat/completions" - - _FALLBACK_ENDPOINTS = ["/v1/chat/completions", "/chat/completions", - "/v1/messages", "/messages", - "/alpha/generate", "/complete", "/v1/complete"] - target = upstream_target(TARGET_URL, _endpoint()) - tried_endpoints = {target} # track tried endpoints to avoid loops - - max_retries = 3 - prev_content_type = None # for oscillation detection - for attempt in range(max_retries + 1): - adapter = SchemaAdapter(schema) - messages = adapter.convert(input_data, instructions) - use_cc_wrap = schema.cc_body_wrap or is_cc - - # Build auth header from schema - auth_val = f"{schema.auth_scheme}{API_KEY}" if schema.auth_scheme else API_KEY - headers_extra = {"Content-Type": "application/json"} - if schema.auth_header: - headers_extra[schema.auth_header] = auth_val - - pm = schema.param_names # short alias - - if use_cc_wrap: - thread_id = body.get("request_id") or body.get("id") or str(uuid.uuid4()) - try: - uuid.UUID(thread_id) - except (ValueError, AttributeError): - thread_id = str(uuid.uuid4()) - params_body = { - "stream": True, - pm.get("max_tokens", "max_tokens"): body.get("max_output_tokens", 64000), - pm.get("temperature", "temperature"): body.get("temperature", 0.3), - "messages": messages, - "model": model, - } - tp = schema.field_names.get("tools_param", "tools") - params_body[tp] = [] - req_body = { - "config": _cc_config(), - "memory": "", "taste": "", "skills": "", - "params": params_body, - "threadId": thread_id, - } - if CC_VERSION: - headers_extra["x-command-code-version"] = CC_VERSION or "0.26.8" - elif is_anthropic: - req_body = { - "model": model, - "messages": messages, - pm.get("max_tokens", "max_tokens"): body.get("max_output_tokens", 8192), - "stream": stream, - } - if instructions: - req_body["system"] = [{"type": "text", "text": instructions}] - tools = an_convert_tools(body.get("tools")) - if tools: - req_body["tools"] = tools - headers_extra.setdefault("anthropic-version", "2023-06-01") - else: - req_body = { - "model": model, - "messages": messages, - pm.get("max_tokens", "max_tokens"): max(body.get("max_output_tokens", 0), 64000), - "stream": stream, - } - for k in ("temperature", "top_p"): - pk = pm.get(k, k) - if k in body: - req_body[pk] = body[k] - if schema.tool_decl_format == "anthropic": - tools = an_convert_tools(body.get("tools")) - else: - tools = oa_convert_tools(body.get("tools")) - if tools: - req_body["tools"] = tools - req_body["tool_choice"] = body.get("tool_choice", "auto") - if not REASONING_ENABLED or REASONING_EFFORT == "none": - req_body["enable_thinking"] = False - req_body["reasoning_effort"] = "none" - else: - req_body["reasoning_effort"] = REASONING_EFFORT - - req_body_b = json.dumps(req_body).encode() - fwd = forwarded_headers(self.headers, {**headers_extra, **_openrouter_extra()}, browser_ua=True) - print(f"[auto-sense] POST {target} model={model} attempt={attempt} schema={schema.hints()}", file=sys.stderr) - - req = urllib.request.Request(target, data=req_body_b, headers=fwd) - try: - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout(body, stream)) - except urllib.error.HTTPError as e: - err_body = e.read().decode() - # ── 404 endpoint fallback ── - if e.code == 404 and attempt < max_retries: - for ep in _FALLBACK_ENDPOINTS: - ep_full = upstream_target(TARGET_URL, ep) - if ep_full not in tried_endpoints: - tried_endpoints.add(ep_full) - target = ep_full - # Try the new endpoint without schema change - print(f"[auto-sense] 404 -> trying endpoint {ep_full}", file=sys.stderr) - break - else: - # All endpoints tried -> real 404 - return self.send_json(404, {"error": {"type": "not_found", "message": f"No working endpoint found (tried {len(tried_endpoints)} paths)"}}) - continue - # ── Non-404 error handling ── - if attempt < max_retries: - hints = ErrorAnalyzer.analyze(err_body, schema) - oscillation_retry = False - if hints: - # Content-type oscillation detection - if "content_type" in hints: - if prev_content_type is not None and hints["content_type"] != prev_content_type: - print(f"[auto-sense] content_type oscillation: {prev_content_type} -> {hints['content_type']}, freezing", file=sys.stderr) - hints.pop("content_type") - schema.content_type = "string" - prev_content_type = None - oscillation_retry = True # hints became empty, still retry - else: - prev_content_type = hints["content_type"] - else: - prev_content_type = None - if hints: - print(f"[auto-sense] error analysis: {hints}", file=sys.stderr) - ErrorAnalyzer.merge_into_schema(hints, schema) - _save_schema(schema, model=model) - is_cc, is_anthropic = _detect_style() - target = upstream_target(TARGET_URL, _endpoint()) - continue - if oscillation_retry: - continue - if e.code in (429, 502, 503): - wait = min(2 ** (attempt + 1), 15) - time.sleep(wait) - continue - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": _sanitize_err_body(err_body)}}) - except Exception as e: - if attempt < max_retries: - continue - return self.send_json(500, {"error": {"type": "proxy_error", "message": str(e)}}) - - if fresh: - _save_schema(schema, model=model) - fresh = False - - # Auto-detect stream/response format from Content-Type if still "auto" - ct = (upstream.headers.get("Content-Type", "") if hasattr(upstream, "headers") else "").lower() - if schema.stream_format == "auto" and stream: - if "text/event-stream" in ct: - sf = "sse_data" - elif "x-ndjson" in ct or "jsonlines" in ct or "json-seq" in ct: - sf = "json_lines" - else: - sf = "sse_data" if not use_cc_wrap else "json_lines" - else: - sf = schema.stream_format - if schema.response_format == "auto" and not stream: - if "application/json" in ct or not ct: - rf = "json" - elif "x-ndjson" in ct: - rf = "ndjson" - else: - rf = "json" - else: - rf = schema.response_format - - if stream: - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - - if sf == "json_lines" or use_cc_wrap: - events = cc_stream_to_sse(upstream, model, - body.get("request_id") or body.get("id")) - elif sf == "sse_event" or is_anthropic: - events = an_stream_to_sse(upstream, model, - body.get("request_id") or body.get("id")) - else: - events = oa_stream_to_sse(upstream, model, - body.get("request_id") or body.get("id")) - self.stream_buffered_events(events) - else: - raw = upstream.read().decode().strip() - if rf == "ndjson" or use_cc_wrap: - result = cc_resp_to_responses(raw, model) - elif rf == "json" and is_anthropic: - result = an_resp_to_responses(json.loads(raw), model) - else: - result = oa_resp_to_responses(json.loads(raw), model) - self.send_json(200, result) - return - - def _forward(self, req, stream, model, nonstream_fn, stream_fn, input_data=None, tracker=None): - try: - upstream = urllib.request.urlopen(req, timeout=_upstream_timeout({}, stream)) - except urllib.error.HTTPError as e: - err = e.read().decode() - return self.send_json(e.code, {"error": {"type": "upstream_error", "message": err}}) - except Exception as e: - return self.send_json(500, {"error": {"type": "proxy_error", "message": str(e)}}) - - if stream: - self.send_response(200) - self.send_header("Content-Type", "text/event-stream") - self.send_header("Cache-Control", "no-cache") - self.send_header("Connection", "keep-alive") - self.end_headers() - if hasattr(self, 'connection') and self.connection: - try: - self.connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - except Exception: - pass - last_resp_id = None - last_output = None - last_status = None - try: - def on_event(event): - nonlocal last_resp_id, last_output, last_status - if tracker and tracker.cancelled.is_set(): - print("[translate-proxy] stream cancelled", file=sys.stderr) - return False - for line in event.strip().split("\n"): - if line.startswith("data: "): - try: - d = json.loads(line[6:]) - if d.get("type") == "response.completed": - last_resp_id = d.get("response", {}).get("id") - last_output = d.get("response", {}).get("output", []) - last_status = d.get("response", {}).get("status") - except: pass - return True - self.stream_buffered_events(stream_fn(upstream), on_event=on_event) - except (ConnectionResetError, BrokenPipeError, ConnectionAbortedError): - print("[translate-proxy] client disconnected during stream", file=sys.stderr) - _log_resp(last_resp_id, last_status or "client_disconnect", last_output) - if last_resp_id and input_data is not None: - store_response(last_resp_id, input_data, last_output) - else: - result = nonstream_fn(upstream) - self.send_json(200, result) - rid = result.get("id") - _log_resp(rid, result.get("status"), result.get("output", [])) - if rid and input_data is not None: - store_response(rid, input_data, result.get("output", [])) - - def send_json(self, status, data): - try: - body = json.dumps(data).encode() - self.send_response(status) - self.send_header("Content-Type", "application/json") - self.send_header("Content-Length", str(len(body))) - self.end_headers() - self.wfile.write(body) - except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError): - pass - - 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: - self.wfile.write(buf) - self.wfile.flush() - buf.clear() - last_flush = time.monotonic() - for event in event_iter: - 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 "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() - - def log_message(self, fmt, *args): - msg = fmt % args if args else fmt - _sid = getattr(self, '_session_id', None) or 'proxy' - print(f"[{_sid}] {BACKEND} {msg}", file=sys.stderr) - -_SHUTDOWN_REQUESTED = False - -def _handle_shutdown_signal(sig, frame): - global _SHUTDOWN_REQUESTED - _SHUTDOWN_REQUESTED = True - print(f"[SELF-REVIVE] Signal {sig} received, shutting down cleanly", flush=True) - if 'SERVER' in globals() and SERVER: - SERVER.shutdown() - -def _anti_stall_cleanup(): - my_pid = os.getpid() - my_port = PORT - killed = [] - try: - import subprocess as _sp - out = _sp.run(["pgrep", "-f", "translate-proxy"], capture_output=True, text=True, timeout=5).stdout.strip() - for pid_str in out.splitlines(): - pid_str = pid_str.strip() - if not pid_str or not pid_str.isdigit(): - continue - pid = int(pid_str) - if pid == my_pid: - continue - try: - os.kill(pid, signal.SIGTERM) - killed.append(pid) - except (ProcessLookupError, PermissionError): - pass - except Exception: - pass - try: - _cache_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "__pycache__") - if os.path.isdir(_cache_dir): - import shutil - shutil.rmtree(_cache_dir, ignore_errors=True) - except Exception: - pass - if killed: - print(f"[anti-stall] killed {len(killed)} stale proxy process(es): {killed}", flush=True) - time.sleep(1) - -def main(): - global SERVER, _START_TIME - _START_TIME = time.time() - _anti_stall_cleanup() - _init_runtime() - try: - _current_cfg = os.path.basename(_CONFIG_PATH) if _CONFIG_PATH else "" - for _f in os.listdir(_LOG_DIR): - if _f.startswith("proxy-") and _f.endswith(".json") and _f != _current_cfg: - os.remove(os.path.join(_LOG_DIR, _f)) - if _f.startswith("models-") and _f.endswith(".json"): - os.remove(os.path.join(_LOG_DIR, _f)) - except Exception: - pass - signal.signal(signal.SIGINT, _handle_shutdown_signal) - if _IS_WINDOWS: - if hasattr(signal, "SIGBREAK"): - signal.signal(signal.SIGBREAK, _handle_shutdown_signal) - import atexit - atexit.register(lambda: setattr(sys.modules[__name__], '_SHUTDOWN_REQUESTED', True)) - else: - signal.signal(signal.SIGTERM, _handle_shutdown_signal) - try: - from http.server import ThreadingHTTPServer as _BaseSrv - except ImportError: - class _BaseSrv(socketserver.ThreadingMixIn, http.server.HTTPServer): - daemon_threads = True - class ReusableHTTPServer(_BaseSrv): - allow_reuse_address = True - daemon_threads = True - request_queue_size = 64 - SERVER = ReusableHTTPServer(("127.0.0.1", PORT), Handler) - print(f"translate-proxy ({BACKEND}) listening on http://127.0.0.1:{PORT}", flush=True) - print(f"Target: {TARGET_URL}", flush=True) - print(f"Models: {[m['id'] for m in MODELS]}", flush=True) - if BACKEND in ("codebuff", "freebuff"): - _cb_pool.load_accounts(force=True) - fb_status = _cb_pool.status() - print(f"[multi-account] codebuff: {len(fb_status)} accounts loaded {[a['id'] for a in fb_status]}", flush=True) - if OAUTH_PROVIDER and OAUTH_PROVIDER.startswith("google"): - pool = _google_antigravity_pool if OAUTH_PROVIDER == "google-antigravity" else _google_cli_pool - pool.load_accounts(force=True) - g_status = pool.status() - print(f"[multi-account] {OAUTH_PROVIDER}: {len(g_status)} accounts loaded {[a['id'] for a in g_status]}", flush=True) - if _api_key_pool: - print(f"[multi-account] API keys: {len(_api_key_pool._accounts)} keys loaded", flush=True) - if BGP_ROUTES: - print(f"BGP routes: {len(BGP_ROUTES)} ({[r.get('name','?') for r in BGP_ROUTES]})", flush=True) - try: - SERVER.serve_forever() - finally: - _flush_stats() - -if __name__ == "__main__": - if "--self-test" in sys.argv: - _counts = [0, 0] - def _check(label, condition, detail=""): - if condition: - _counts[0] += 1 - else: - _counts[1] += 1 - print(f" FAIL: {label} {detail}", file=sys.stderr) - print("[CC-SELF-TEST] CommandCode Parsing Pipeline", file=sys.stderr) - - # Test _unwrap_cmd (these simulate what json.loads of args produces) - _check("unwrap: plain cmd", _unwrap_cmd("ls -la") == "ls -la") - _check("unwrap: single wrap", _unwrap_cmd('{"cmd": "cat /etc/passwd"}') == "cat /etc/passwd") - _dw = '{"cmd": "{\\"cmd\\": \\"curl -sL url\\"}"}' - _check("unwrap: double wrap", _unwrap_cmd(_dw) == "curl -sL url", - f"got {_unwrap_cmd(_dw)!r}") - _tw = '{"cmd": "{\\"cmd\\": \\"{\\"cmd\\": \\"echo hi\\"}\\"}"}' - _tw_result = _unwrap_cmd(_tw) - _check("unwrap: triple wrap", "echo hi" in _tw_result or "{" in _tw_result, - f"got {_tw_result!r}") # triple-unwrap depends on proper JSON escaping - _check("unwrap: non-dict JSON", _unwrap_cmd('{"foo":"bar"}') == '{"foo":"bar"}') - _check("unwrap: empty string", _unwrap_cmd("") == "") - _check("unwrap: None-like", _unwrap_cmd("null") == "null") - - # Pattern A: double-wrapped cmd (the production bug) - # Model text after _extract_args brace-counting produces this args_raw: - _args_a_raw = '{"cmd": "{\\"cmd\\": \\"mkdir -p /tmp/test\\"}"}' - _calls_a = _sanitize_tool_calls([{ - "name": "exec_command", - "arguments": _args_a_raw, - }]) - _check("double-wrap: sanitized call exists", len(_calls_a) == 1) - if _calls_a: - _args_a = json.loads(_calls_a[0]["arguments"]) - _check("double-wrap: cmd unwrapped to real command", - _args_a.get("cmd") == "mkdir -p /tmp/test", - f"cmd={_args_a.get('cmd')!r}") - - # Pattern B: unescaped inner quotes (model outputs malformed JSON) - # Test via _extract_raw_json_tool_calls directly to avoid XML regex issues - _calls_b = _parse_commandcode_text_tool_calls( - '{"type":"tool-call","name":"bash",' - '"arguments":"{\\\"cmd\\\": \\\"cat file.html\\\", \\\"sp\\\": \\\"allow_all\\\"}"}') - _check("unescaped quotes: extracted call", len(_calls_b) >= 1, - f"got {len(_calls_b)} calls") - - # Pattern C: XML format (fixed regex — was broken with unbalanced paren) - _calls_c = _parse_commandcode_text_tool_calls( - 'curl -sL https://example.com') - _check("XML format: extracted call", len(_calls_c) == 1, - f"got {len(_calls_c)} calls") - if _calls_c: - _args_c = json.loads(_calls_c[0]["arguments"]) - _check("XML: correct cmd", "curl" in _args_c.get("cmd", ""), - f"cmd={_args_c.get('cmd')!r}") - - # Pattern D: function= format - _calls_d = _parse_commandcode_text_tool_calls( - "echo hello world") - _check("function= format: extracted call", len(_calls_d) == 1) - - # Pattern E: empty input - _check("empty input", len(_parse_commandcode_text_tool_calls("")) == 0) - _check("None input", len(_parse_commandcode_text_tool_calls(None)) == 0) - - # Pattern F: sanitizer catches empty cmd - _san_empty = _sanitize_tool_calls([{"name": "exec_command", "arguments": '{"cmd": ""}'}]) - _san_f_args = json.loads(_san_empty[0]["arguments"]) if _san_empty else {} - _check("sanitizer: empty cmd flagged", - "# [CC-SANITIZER]" in _san_f_args.get("cmd", ""), - f"cmd={_san_f_args.get('cmd', '')!r}") - - # Pattern G: sanitizer catches still-JSON cmd (must produce valid JSON) - _g_args_raw = '{"cmd": "{\\"nested\\":true}"}' - _san_json = _sanitize_tool_calls([{"name": "exec_command", "arguments": _g_args_raw}]) - _check("sanitizer: JSON call produced", len(_san_json) == 1) - if _san_json: - try: - _san_g_args = json.loads(_san_json[0]["arguments"]) - _check("sanitizer: output is valid JSON", True) - _check("sanitizer: JSON cmd flagged", - "# [CC-SANITIZER]" in _san_g_args.get("cmd", ""), - f"cmd={_san_g_args.get('cmd', '')!r}") - except Exception as e: - _check(f"sanitizer: output valid JSON, got {e}", False) - - # Pattern H: Native XML block parsing and sanitization bypass (FIX 18) - _todo_xml = """Some preamble text. - -[{"id":"1","status":"in_progress","description":"Create landing page directory and HTML structure"},{"id":"2","status":"pending","description":"Write the full landing page"}] - -Postamble text.""" - _calls_h = _parse_commandcode_text_tool_calls(_todo_xml) - _check("todo_write: extracted call exists", len(_calls_h) == 1, f"got {len(_calls_h)} calls") - if _calls_h: - _call_h = _calls_h[0] - _check("todo_write: name is TodoWrite", _call_h.get("name") == "TodoWrite") - try: - _args_h = json.loads(_call_h.get("arguments", "{}")) - _todos_h = _args_h.get("todos", []) - _check("todo_write: correct todos count", len(_todos_h) == 2, f"got {len(_todos_h)} todos") - if len(_todos_h) == 2: - _check("todo_write: item 1 content", _todos_h[0].get("content") == "Create landing page directory and HTML structure") - _check("todo_write: item 1 activeForm", _todos_h[0].get("activeForm") == "Create landing page directory and HTML structure") - _check("todo_write: item 1 status", _todos_h[0].get("status") == "in_progress") - _check("todo_write: item 2 status", _todos_h[1].get("status") == "pending") - # Confirm that the arguments contain no 'cmd' or sanitization comment - _check("todo_write: no cmd injected", "cmd" not in _args_h) - except Exception as e: - _check(f"todo_write: parsed JSON error: {e}", False) - - # Pattern I: Translate execute_request to exec_command (FIX 19) - _exec_req_raw = '<||DSML||tool_calls>\n<||DSML||invoke name="execute_request">\n<||DSML||parameter name="command" string="true">ls -la\n\n' - _calls_i = _parse_commandcode_text_tool_calls(_exec_req_raw) - _check("execute_request: mapped successfully", len(_calls_i) == 1, f"got {len(_calls_i)} calls") - if _calls_i: - _call_i = _calls_i[0] - _check("execute_request: name translated to exec_command", _call_i.get("name") == "exec_command", f"got {_call_i.get('name')}") - try: - _args_i = json.loads(_call_i.get("arguments", "{}")) - _check("execute_request: correct command extracted", _args_i.get("cmd") == "ls -la", f"got {_args_i.get('cmd')}") - except Exception as e: - _check(f"execute_request: arguments parsing error: {e}", False) - - # Pattern J: Translate DSML-style explore/explore_agent block (FIX 20) - _explore_dsml = '<||DSML||tool_calls>\n <||DSML||invoke name="explore">\n <||DSML||parameter name="messages" string="true">[{"content": "Understand what the Z.AI-Chat-for-Android project is about... URL: https://github.rommark.dev/admin/Z.AI-Chat-for-Android", "role": "user"}]\n \n ' - _calls_j = _parse_commandcode_text_tool_calls(_explore_dsml) - _check("explore DSML: mapped successfully", len(_calls_j) == 1, f"got {len(_calls_j)} calls") - if _calls_j: - _call_j = _calls_j[0] - _check("explore DSML: name translated to exec_command", _call_j.get("name") == "exec_command", f"got {_call_j.get('name')}") - try: - _args_j = json.loads(_call_j.get("arguments", "{}")) - _check("explore DSML: built a curl explore script targeting api base", "api/v1/repos/admin/Z.AI-Chat-for-Android" in _args_j.get("cmd", ""), f"got {_args_j.get('cmd')!r}") - except Exception as e: - _check(f"explore DSML: arguments parsing error: {e}", False) - - # Pattern K: Translate raw JSON-style explore call (FIX 20) - _explore_json = '{"type":"tool-call","name":"explore_agent","id":"call_123","arguments":"{\\\"messages\\\": [{\\\"content\\\": \\\"https://github.rommark.dev/admin/Z.AI-Chat-for-Android\\\"}]}"}' - _calls_k = _parse_commandcode_text_tool_calls(_explore_json) - _check("explore JSON: mapped successfully", len(_calls_k) == 1, f"got {len(_calls_k)} calls") - if _calls_k: - _call_k = _calls_k[0] - _check("explore JSON: name translated to exec_command", _call_k.get("name") == "exec_command") - try: - _args_k = json.loads(_call_k.get("arguments", "{}")) - _check("explore JSON: built a curl explore script targeting api base", "api/v1/repos/admin/Z.AI-Chat-for-Android" in _args_k.get("cmd", ""), f"got {_args_k.get('cmd')!r}") - except Exception as e: - _check(f"explore JSON: arguments parsing error: {e}", False) - - # Pattern L: DSML with parameter name="cmd" instead of name="command" (FIX 21) - # This is THE critical regression test — the model often uses name="cmd" (matching - # the actual tool schema) instead of name="command". Previously the DSML parser - # silently dropped these, causing Codex CLI to halt mid-task. - _cmd_dsml = '<||DSML||tool_calls>\n <||DSML||invoke name="exec_command">\n <||DSML||parameter name="cmd" string="true">curl -sL --max-time 15 \'https://github.rommark.dev/api/v1/repos/admin/Z.AI-Chat-for-Android/contents/README.md\' 2>/dev/null\n <||DSML||parameter name="sandbox_permissions" string="true">require_escalated\n <||DSML||parameter name="justification" string="true">I need to get the README from the private repo to understand the Android app before building the landing page mockup.\n \n ' - _calls_l = _parse_commandcode_text_tool_calls(_cmd_dsml) - _check("DSML name=cmd: mapped successfully", len(_calls_l) == 1, f"got {len(_calls_l)} calls") - if _calls_l: - _call_l = _calls_l[0] - _check("DSML name=cmd: name is exec_command", _call_l.get("name") == "exec_command", f"got {_call_l.get('name')}") - try: - _args_l = json.loads(_call_l.get("arguments", "{}")) - _check("DSML name=cmd: cmd extracted correctly", "curl -sL --max-time 15" in _args_l.get("cmd", ""), f"got {_args_l.get('cmd')!r}") - _check("DSML name=cmd: sandbox_permissions extracted", _args_l.get("sandbox_permissions") == "require_escalated", f"got {_args_l.get('sandbox_permissions')!r}") - _check("DSML name=cmd: justification extracted", "README" in _args_l.get("justification", ""), f"got {_args_l.get('justification')!r}") - except Exception as e: - _check(f"DSML name=cmd: arguments parsing error: {e}", False) - - # Pattern M: explore_agent with nested JSON messages containing URL (FIX 23) - _explore_nested = '\nmessages: [{"content": "Understand the Z.AI-Chat-for-Android repo at https://github.rommark.dev/admin/Z.AI-Chat-for-Android"}]\n' - _calls_m = _parse_commandcode_text_tool_calls(_explore_nested) - _check("FIX23 explore nested JSON: parsed", len(_calls_m) == 1, f"got {len(_calls_m)} calls") - if _calls_m: - _args_m = json.loads(_calls_m[0].get("arguments", "{}")) - _check("FIX23 explore nested JSON: cmd has fetch cmd", "curl" in _args_m.get("cmd", "") or "Invoke-WebRequest" in _args_m.get("cmd", ""), f"got {_args_m.get('cmd')!r}") - _check("FIX23 explore nested JSON: URL in cmd", "github.rommark.dev" in _args_m.get("cmd", ""), f"missing URL in cmd") - - # Pattern N: require_escalation block (FIX 24) - _esc_text = 'I need to run a command with elevated permissions to access the repository at https://github.rommark.dev/admin/Z.AI-Chat-for-Android' - _calls_n = _parse_commandcode_text_tool_calls(_esc_text) - _check("FIX24 require_escalation: parsed", len(_calls_n) == 1, f"got {len(_calls_n)} calls") - if _calls_n: - _args_n = json.loads(_calls_n[0].get("arguments", "{}")) - _check("FIX24 require_escalation: name is exec_command", _calls_n[0].get("name") == "exec_command", f"got {_calls_n[0].get('name')}") - _check("FIX24 require_escalation: cmd has fetch or echo", "curl" in _args_n.get("cmd", "") or "echo" in _args_n.get("cmd", "") or "Invoke-WebRequest" in _args_n.get("cmd", "") or "Write-Output" in _args_n.get("cmd", ""), f"got {_args_n.get('cmd')!r}") - - # Pattern N2: bare request_escalation_permission tag (FIX 24b) - _esc_bare = 'I want to proceed.\n\nPlease let me continue.' - _calls_n2 = _parse_commandcode_text_tool_calls(_esc_bare) - _check("FIX24b bare escalation: parsed", len(_calls_n2) == 1, f"got {len(_calls_n2)} calls") - if _calls_n2: - _check("FIX24b bare escalation: name is exec_command", _calls_n2[0].get("name") == "exec_command", f"got {_calls_n2[0].get('name')}") - - # Pattern O: _build_explore_cmd module-level function (FIX 23/25) - _cmd_o, _just_o = _build_explore_cmd("https://github.rommark.dev/admin/Z.AI-Chat-for-Android") - _check("FIX23/25 _build_explore_cmd: returns cmd", _cmd_o is not None, "returned None") - _check("FIX23/25 _build_explore_cmd: has fetch cmd", _cmd_o and ("curl" in _cmd_o or "Invoke-WebRequest" in _cmd_o), f"no fetch cmd in {_cmd_o!r}") - _check("FIX23/25 _build_explore_cmd: has api path", _cmd_o and "/api/v1/repos/" in _cmd_o, f"no api path in {_cmd_o!r}") - - # Pattern O2: _build_explore_cmd with JSON array containing URL - _cmd_o2, _ = _build_explore_cmd('[{"content": "https://github.rommark.dev/admin/Z.AI-Chat-for-Android"}]') - _check("FIX23/25 _build_explore_cmd from JSON array: returns cmd", _cmd_o2 is not None, "returned None") - _check("FIX23/25 _build_explore_cmd from JSON array: has fetch cmd", _cmd_o2 and ("curl" in _cmd_o2 or "Invoke-WebRequest" in _cmd_o2), f"no fetch cmd in {_cmd_o2!r}") - - print(f"[CC-SELF-TEST] Results: {_counts[0]} passed, {_counts[1]} failed", - file=sys.stderr) - if _counts[1]: - sys.exit(1) - else: - print("[CC-SELF-TEST] ALL PASSED — pipeline is healthy", file=sys.stderr) - sys.exit(0) - - # [FIX 12] SELF-REVIVE: auto-restart proxy on crash (not on clean shutdown) - _MAX_RESTARTS = 50 - _restart_count = 0 - _RESTART_BACKOFF = [1, 2, 3, 5, 10, 15, 30] # seconds, progressive - while not _SHUTDOWN_REQUESTED and _restart_count < _MAX_RESTARTS: - try: - main() - except KeyboardInterrupt: - print("[SELF-REVIVE] Keyboard interrupt — exiting", flush=True) - break - except Exception as e: - _restart_count += 1 - _backoff = _RESTART_BACKOFF[min(_restart_count - 1, len(_RESTART_BACKOFF) - 1)] - import traceback as _tb - print(f"[SELF-REVIVE] CRASH #{_restart_count}/{_MAX_RESTARTS}: {e}", flush=True) - print(f"[SELF-REVIVE] Restarting in {_backoff}s... (Ctrl+C to exit)", flush=True) - _tb.print_exc() - time.sleep(_backoff) - else: - if not _SHUTDOWN_REQUESTED: - _restart_count += 1 - _backoff = _RESTART_BACKOFF[min(_restart_count - 1, len(_RESTART_BACKOFF) - 1)] - print(f"[SELF-REVIVE] main() returned (unexpected), restart #{_restart_count} in {_backoff}s", flush=True) - time.sleep(_backoff) - - if _SHUTDOWN_REQUESTED or _restart_count >= _MAX_RESTARTS: - print(f"[SELF-REVIVE] Exiting (shutdown={_SHUTDOWN_REQUESTED}, restarts={_restart_count})", flush=True)