Files
karuo-ai/01_卡资(金)/金仓_存储备份/脚本/cockpit_codex_launch_fix.py
2026-07-19 00:21:46 +08:00

158 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""修复 Cockpit Tools 无法启动 Codex路径、当前账号、auth 同步。"""
from __future__ import annotations
import json
import os
import shutil
import subprocess
import sys
import time
from datetime import datetime, timezone
from pathlib import Path
COCKPIT = Path.home() / ".antigravity_cockpit"
CODEX_HOME = Path.home() / ".codex"
CODEX_APP = Path("/Applications/Codex.app")
HEALTHY_OAUTH_ID = "codex_4d0c0e374407d42d21202d01cd05eaf3" # sled · 无 401
APIKEY_ID = "codex_apikey_5df7aea89c1abb33b2043a4d3cad9071" # 龙虾U盘AI
USE_APIKEY = "--apikey" in sys.argv
def ts() -> str:
return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
def backup(path: Path) -> None:
if path.exists():
shutil.copy2(path, f"{path}.bak.{datetime.now().strftime('%Y%m%d%H%M%S')}")
def load_json(path: Path) -> dict:
return json.loads(path.read_text(encoding="utf-8"))
def save_json(path: Path, data: dict) -> None:
backup(path)
path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
def write_auth_from_account(account: dict) -> None:
tokens = account.get("tokens") or {}
if not tokens.get("access_token"):
raise SystemExit(f"账号 {account.get('id')} 无 access_token")
auth = {
"OPENAI_API_KEY": account.get("openai_api_key"),
"last_refresh": ts(),
"tokens": {
"access_token": tokens.get("access_token", ""),
"account_id": account.get("account_id"),
"id_token": tokens.get("id_token", ""),
"refresh_token": tokens.get("refresh_token", ""),
},
}
auth_path = CODEX_HOME / "auth.json"
backup(auth_path)
auth_path.write_text(json.dumps(auth, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
def fix_cockpit_path() -> str:
cfg_path = COCKPIT / "config.json"
cfg = load_json(cfg_path)
old = cfg.get("codex_app_path", "")
cfg["codex_app_path"] = str(CODEX_APP)
save_json(cfg_path, cfg)
return old
def set_current_account(target_id: str) -> None:
idx_path = COCKPIT / "codex_accounts.json"
idx = load_json(idx_path)
idx["current_account_id"] = target_id
save_json(idx_path, idx)
inst_path = COCKPIT / "codex_instances.json"
inst = load_json(inst_path)
ds = inst.setdefault("defaultSettings", {})
ds["bindAccountId"] = target_id
save_json(inst_path, inst)
def sanitize_config_toml(text: str) -> str:
"""去掉 Codex 无法解析的孤立 ensure-hub 伪表头。"""
out = []
for line in text.splitlines():
if line.strip().startswith('["/Users/karuo/.persistent-chat-local/ensure-hub.sh"'):
continue
out.append(line)
while out and not out[-1].strip():
out.pop()
return "\n".join(out) + "\n"
def apply_api_provider(account: dict) -> None:
"""为龙虾U盘AI 写入 provider_secretsconfig.toml 仅做 sanitize避免破坏 TOML。"""
provider_id = "longxia_udisk_ai"
api_key = account.get("openai_api_key") or ""
base_url = (account.get("api_base_url") or "").rstrip("/")
if not api_key or not base_url:
raise SystemExit("API Key 账号缺少 openai_api_key 或 api_base_url")
secrets = CODEX_HOME / "provider_secrets.toml"
lines = secrets.read_text(encoding="utf-8").splitlines() if secrets.exists() else []
out, skip = [], False
for line in lines:
if line.strip() == f"[{provider_id}]":
skip = True
continue
if skip and line.startswith("["):
skip = False
if skip:
continue
out.append(line)
while out and not out[-1].strip():
out.pop()
out.extend([f"[{provider_id}]", f'api_key = "{api_key}"', ""])
backup(secrets)
secrets.write_text("\n".join(out) + "\n", encoding="utf-8")
cfg = CODEX_HOME / "config.toml"
if cfg.exists():
backup(cfg)
cfg.write_text(sanitize_config_toml(cfg.read_text(encoding="utf-8")), encoding="utf-8")
print("[WARN] API Key 线路请用 Cockpit 切换;勿手改 config.toml 追加 provider 块")
def restart_codex() -> None:
subprocess.run(["killall", "Codex"], check=False)
time.sleep(1.5)
subprocess.run(["/usr/bin/open", "-a", "Codex"], check=True)
def main() -> None:
if not CODEX_APP.exists():
raise SystemExit(f"未找到 {CODEX_APP}")
old_path = fix_cockpit_path()
print(f"[OK] codex_app_path: {old_path!r} -> {CODEX_APP}")
api_acct = load_json(COCKPIT / "codex_accounts" / f"{APIKEY_ID}.json")
oauth_acct = load_json(COCKPIT / "codex_accounts" / f"{HEALTHY_OAUTH_ID}.json")
if USE_APIKEY:
set_current_account(APIKEY_ID)
write_auth_from_account(oauth_acct)
apply_api_provider(api_acct)
print(f"[OK] 当前账号=龙虾U盘AIOAuth 壳={oauth_acct.get('email')}")
else:
set_current_account(HEALTHY_OAUTH_ID)
write_auth_from_account(oauth_acct)
print(f"[OK] 当前账号={oauth_acct.get('email')}")
restart_codex()
print("[OK] 已重启 /Applications/Codex.app")
if __name__ == "__main__":
main()