diff --git a/codex-launcher_3.9.7_all.deb b/codex-launcher_3.9.7_all.deb index 1ff8129..fce6636 100644 Binary files a/codex-launcher_3.9.7_all.deb and b/codex-launcher_3.9.7_all.deb differ diff --git a/src/translate-proxy.py b/src/translate-proxy.py index 9597080..0d3ff15 100755 --- a/src/translate-proxy.py +++ b/src/translate-proxy.py @@ -294,15 +294,15 @@ _conn_pool = {} _STREAM_IDLE_TIMEOUT = 300 -_FREEBUFF_AUTH_URL = "https://codebuff.com" -_FREEBUFF_API_URL = "https://www.codebuff.com" -_FREEBUFF_AGENT_MAP = { +_CODEBUFF_AUTH_URL = "https://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", } -_FREEBUFF_CREDS_PATH = os.path.join(os.path.expanduser("~"), ".config", "manicode", "credentials.json") +_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() @@ -312,7 +312,7 @@ def _get_codebuff_token(): if _codebuff_token_cache["token"] and _codebuff_token_cache["checked"] > time.time() - 300: return _codebuff_token_cache["token"] try: - with open(_FREEBUFF_CREDS_PATH) as f: + 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 "" @@ -321,7 +321,7 @@ def _get_codebuff_token(): _codebuff_token_cache["checked"] = time.time() return token except Exception as e: - print(f"[codebuff] no credentials at {_FREEBUFF_CREDS_PATH}: {e}", file=sys.stderr) + print(f"[codebuff] no credentials at {_CODEBUFF_CREDS_PATH}: {e}", file=sys.stderr) return "" def _codebuff_get_session(token, model): @@ -330,7 +330,7 @@ def _codebuff_get_session(token, model): if sc["instance_id"] and sc["expires"] > time.time() + 60 and sc["model"] == model: return sc["instance_id"] try: - url = f"{_FREEBUFF_API_URL}/api/v1/freebuff/session" + url = f"{_CODEBUFF_API_URL}/api/v1/freebuff/session" body = json.dumps({"model": model}).encode() req = urllib.request.Request(url, data=body, headers={ "Content-Type": "application/json", @@ -378,7 +378,7 @@ def _codebuff_get_session(token, model): return None def _codebuff_start_run(token, agent_id): - url = f"{_FREEBUFF_API_URL}/api/v1/agent-runs" + 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", @@ -410,7 +410,7 @@ def _codebuff_start_run(token, agent_id): return None, ("proxy_error", 502, 0, str(e)) def _codebuff_finish_run(token, run_id, status="completed"): - url = f"{_FREEBUFF_API_URL}/api/v1/agent-runs" + 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={ @@ -516,10 +516,10 @@ class AccountPool: class CodebuffAccountPool(AccountPool): def _do_load(self): - if not os.path.exists(_FREEBUFF_CREDS_PATH): + if not os.path.exists(_CODEBUFF_CREDS_PATH): return None try: - with open(_FREEBUFF_CREDS_PATH) as f: + with open(_CODEBUFF_CREDS_PATH) as f: creds = json.load(f) except Exception: return None @@ -588,14 +588,14 @@ class APIKeyPool(AccountPool): def load_accounts(self, force=False): return len(self._accounts) -_fb_pool = CodebuffAccountPool("codebuff") +_cb_pool = CodebuffAccountPool("codebuff") _google_antigravity_pool = GoogleAccountPool("antigravity") _google_cli_pool = GoogleAccountPool("cli") def _get_codebuff_account(): """Return (token, account_dict) for best available codebuff account.""" - _fb_pool.load_accounts() - acct = _fb_pool.get() + _cb_pool.load_accounts() + acct = _cb_pool.get() if not acct: return "", None return acct["token"], acct @@ -1150,7 +1150,7 @@ def _ds_rebuild_tool_history(messages): rebuilt.append(msg) return rebuilt -def _fb_input_to_messages(input_data, instructions=""): +def _cb_input_to_messages(input_data, instructions=""): msgs = [] tool_name_by_id = {} pending_tool_calls = [] @@ -4038,8 +4038,8 @@ class Handler(http.server.BaseHTTPRequestHandler): elif self.path in ("/v1/accounts", "/accounts"): info = {"provider": BACKEND, "oauth_provider": OAUTH_PROVIDER} if BACKEND == "codebuff": - info["accounts"] = _fb_pool.status() - info["total"] = len(_fb_pool._accounts) + 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() @@ -5214,24 +5214,24 @@ class Handler(http.server.BaseHTTPRequestHandler): store_response(rid, body.get("input", ""), result.get("output", [])) def _handle_codebuff(self, body, model, stream, tracker=None): - agent_id = _FREEBUFF_AGENT_MAP.get(model) + agent_id = _CODEBUFF_AGENT_MAP.get(model) if not agent_id: matched = None - for m in _FREEBUFF_AGENT_MAP: + for m in _CODEBUFF_AGENT_MAP: if model.lower().replace("/", "").replace("-", "") in m.lower().replace("/", "").replace("-", ""): matched = m break if matched: - agent_id = _FREEBUFF_AGENT_MAP[matched] + agent_id = _CODEBUFF_AGENT_MAP[matched] model = matched else: fallback_model = "deepseek/deepseek-v4-flash" - agent_id = _FREEBUFF_AGENT_MAP.get(fallback_model, "base2-free-deepseek-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 - _fb_pool.load_accounts() - pool_status = _fb_pool.status() + _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", @@ -5252,10 +5252,10 @@ class Handler(http.server.BaseHTTPRequestHandler): if not run_id: if run_err and run_err[0] == "rate_limit_error": retry_s = run_err[2] - _fb_pool.mark_rate_limited(acct, retry_s) + _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: - _fb_pool.mark_rate_limited(acct, 60) + _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 @@ -5268,14 +5268,14 @@ class Handler(http.server.BaseHTTPRequestHandler): 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) - _fb_pool.mark_rate_limited(acct, retry_s) + _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 = _fb_input_to_messages(input_data, instructions) + messages = _cb_input_to_messages(input_data, instructions) messages = _ds_rebuild_tool_history(messages) metadata = { @@ -5301,7 +5301,7 @@ class Handler(http.server.BaseHTTPRequestHandler): if body.get("tool_choice"): chat_body["tool_choice"] = body["tool_choice"] - target = f"{_FREEBUFF_API_URL}/api/v1/chat/completions" + target = f"{_CODEBUFF_API_URL}/api/v1/chat/completions" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {token}", @@ -5336,13 +5336,13 @@ class Handler(http.server.BaseHTTPRequestHandler): 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." - _fb_pool.mark_rate_limited(acct, duration) + _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._fb_retry_thinking_disabled(body, model, token, agent_id, stream, tracker, input_data, instructions, err_body, acct) + 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)}}) @@ -5447,14 +5447,14 @@ class Handler(http.server.BaseHTTPRequestHandler): except (BrokenPipeError, ConnectionResetError, ConnectionAbortedError): return - def _fb_retry_thinking_disabled(self, body, model, token, agent_id, stream, tracker, input_data, instructions, original_error, acct=None): + 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 = _fb_input_to_messages(input_data, instructions) + messages = _cb_input_to_messages(input_data, instructions) _codebuff_hard_disable_reasoning(messages) metadata = {"run_id": run_id, "cost_mode": "free"} if instance_id: @@ -5473,7 +5473,7 @@ class Handler(http.server.BaseHTTPRequestHandler): chat_body["tools"] = tools if body.get("tool_choice"): chat_body["tool_choice"] = body["tool_choice"] - target = f"{_FREEBUFF_API_URL}/api/v1/chat/completions" + target = f"{_CODEBUFF_API_URL}/api/v1/chat/completions" headers = {"Content-Type": "application/json", "Authorization": f"Bearer {token}", "User-Agent": "codex-launcher/3.9.7", "x-codebuff-model": model} if instance_id: headers["x-codebuff-instance-id"] = instance_id @@ -5897,8 +5897,8 @@ def main(): print(f"Target: {TARGET_URL}", flush=True) print(f"Models: {[m['id'] for m in MODELS]}", flush=True) if BACKEND == "codebuff": - _fb_pool.load_accounts(force=True) - fb_status = _fb_pool.status() + _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