fix(codex-accounts): add remove command and ignore quota artifacts in account list
This commit is contained in:
@@ -19,6 +19,18 @@ def ensure_dirs():
|
||||
if not ACCOUNTS_DIR.exists():
|
||||
ACCOUNTS_DIR.mkdir(parents=True)
|
||||
|
||||
|
||||
def account_files():
|
||||
"""Real saved account snapshots (exclude hidden/quota artifacts)."""
|
||||
ensure_dirs()
|
||||
out = []
|
||||
for f in ACCOUNTS_DIR.glob("*.json"):
|
||||
n = f.name
|
||||
if n.startswith('.') or n.endswith('.quota.json'):
|
||||
continue
|
||||
out.append(f)
|
||||
return out
|
||||
|
||||
def decode_jwt_payload(token):
|
||||
try:
|
||||
# JWT is header.payload.signature
|
||||
@@ -103,7 +115,7 @@ def resolve_active_profile():
|
||||
if not AUTH_FILE.exists():
|
||||
return None
|
||||
|
||||
for f in ACCOUNTS_DIR.glob("*.json"):
|
||||
for f in account_files():
|
||||
if is_current(f):
|
||||
info = get_account_info(f) or {}
|
||||
return f.stem, info.get("email", "unknown")
|
||||
@@ -201,7 +213,7 @@ def cmd_list(verbose: bool = False, json_mode: bool = False):
|
||||
accounts = []
|
||||
max_name = 0
|
||||
|
||||
for f in sorted(ACCOUNTS_DIR.glob("*.json")):
|
||||
for f in sorted(account_files()):
|
||||
name = f.stem
|
||||
max_name = max(max_name, len(name))
|
||||
active = is_current(f)
|
||||
@@ -287,7 +299,7 @@ def _resolve_matching_account_by_email(email: str) -> Path | None:
|
||||
return None
|
||||
|
||||
matches: list[Path] = []
|
||||
for f in ACCOUNTS_DIR.glob("*.json"):
|
||||
for f in account_files():
|
||||
info = get_account_info(f) or {}
|
||||
got = (info.get("email") or "").strip().lower()
|
||||
if got and got == want:
|
||||
@@ -620,7 +632,7 @@ def cmd_auto(json_mode=False):
|
||||
import time
|
||||
ensure_dirs()
|
||||
|
||||
accounts = [f.stem for f in ACCOUNTS_DIR.glob("*.json") if not f.name.startswith('.')]
|
||||
accounts = [f.stem for f in account_files()]
|
||||
if not accounts:
|
||||
if json_mode:
|
||||
print('{"error": "No accounts found"}')
|
||||
@@ -631,7 +643,7 @@ def cmd_auto(json_mode=False):
|
||||
# Save current account to restore if needed
|
||||
original_account = None
|
||||
if AUTH_FILE.exists():
|
||||
for acct_file in ACCOUNTS_DIR.glob("*.json"):
|
||||
for acct_file in account_files():
|
||||
if acct_file.read_bytes() == AUTH_FILE.read_bytes():
|
||||
original_account = acct_file.stem
|
||||
break
|
||||
@@ -750,7 +762,7 @@ def cmd_use(name):
|
||||
if not source.exists():
|
||||
print(f"❌ Account '{name}' not found.")
|
||||
print("Available accounts:")
|
||||
for f in ACCOUNTS_DIR.glob("*.json"):
|
||||
for f in account_files():
|
||||
print(f" - {f.stem}")
|
||||
return
|
||||
|
||||
@@ -761,6 +773,34 @@ def cmd_use(name):
|
||||
info = get_account_info(source)
|
||||
print(f"✅ Switched to account: {name} ({info.get('email')})")
|
||||
|
||||
|
||||
def cmd_remove(name: str):
|
||||
ensure_dirs()
|
||||
removed = []
|
||||
|
||||
targets = [
|
||||
ACCOUNTS_DIR / f"{name}.json",
|
||||
ACCOUNTS_DIR / f".{name}.quota.json",
|
||||
ACCOUNTS_DIR / f"{name}.quota.json",
|
||||
ACCOUNTS_DIR / f".{name}.cache.json",
|
||||
ACCOUNTS_DIR / f"{name}.cache.json",
|
||||
ACCOUNTS_DIR / f".{name}.meta.json",
|
||||
ACCOUNTS_DIR / f"{name}.meta.json",
|
||||
]
|
||||
|
||||
for p in targets:
|
||||
if p.exists():
|
||||
try:
|
||||
p.unlink()
|
||||
removed.append(p.name)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if removed:
|
||||
print(f"✅ Removed '{name}': {', '.join(removed)}")
|
||||
else:
|
||||
print(f"ℹ️ Nothing to remove for '{name}'")
|
||||
|
||||
def get_token_email(auth_path) -> str:
|
||||
"""Extract email from a token file."""
|
||||
info = get_account_info(auth_path) or {}
|
||||
@@ -878,6 +918,9 @@ def main():
|
||||
save_parser.add_argument("name", help="Name to save the account as")
|
||||
save_parser.add_argument("--force", action="store_true", help="Force overwrite even if emails don't match")
|
||||
|
||||
rm_parser = subparsers.add_parser("remove", help="Remove account and related local artifacts")
|
||||
rm_parser.add_argument("name", help="Account name to remove")
|
||||
|
||||
auto_parser = subparsers.add_parser("auto", help="Switch to the account with most quota available")
|
||||
auto_parser.add_argument("--json", action="store_true", help="Output as JSON")
|
||||
|
||||
@@ -892,6 +935,8 @@ def main():
|
||||
cmd_use(args.name)
|
||||
elif args.command == "save":
|
||||
cmd_save(args.name, force=bool(getattr(args, "force", False)))
|
||||
elif args.command == "remove":
|
||||
cmd_remove(args.name)
|
||||
elif args.command == "auto":
|
||||
cmd_auto(json_mode=bool(getattr(args, "json", False)))
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user