Download objectstore_sync.py from pjpjq/daili: direct link, hf CLI and curl.
- Browser
- Download file 16.8 kB
-
https://huggingface.co/spaces/pjpjq/daili/resolve/main/objectstore_sync.py
- Command line
-
hf download hf://spaces/pjpjq/daili/objectstore_sync.py
-
curl -L -o objectstore_sync.py https://huggingface.co/spaces/pjpjq/daili/resolve/main/objectstore_sync.py
16.8 kB
| #!/usr/bin/env python3 | |
| from __future__ import annotations | |
| import argparse | |
| import hashlib | |
| import json | |
| import os | |
| import shutil | |
| import subprocess | |
| import sys | |
| from datetime import datetime, timezone | |
| from pathlib import Path | |
| from tempfile import NamedTemporaryFile | |
| from urllib.request import Request, urlopen | |
| from urllib.error import HTTPError, URLError | |
| from codex_ws_auths import enable_codex_auth_websockets | |
| from xai_auth_proxy import enforce_config_proxy_url, parse_proxy_urls, stable_proxy_for_auth | |
| def env_required(name: str) -> str: | |
| value = os.environ.get(name, "").strip() | |
| if not value: | |
| raise SystemExit(f"missing required env: {name}") | |
| return value | |
| MC_BIN = os.environ.get("MC_BIN", "mc") | |
| ALIAS = os.environ.get("OBJECTSTORE_ALIAS", "daili-objectstore").strip() or "daili-objectstore" | |
| ENDPOINT = env_required("OBJECTSTORE_ENDPOINT") | |
| ACCESS_KEY = env_required("OBJECTSTORE_ACCESS_KEY") | |
| SECRET_KEY = env_required("OBJECTSTORE_SECRET_KEY") | |
| BUCKET = env_required("OBJECTSTORE_BUCKET") | |
| ROOT = Path(env_required("OBJECTSTORE_ROOT")).resolve() | |
| CONFIG_FALLBACK = os.environ.get("OBJECTSTORE_CONFIG_FALLBACK", "").strip() | |
| REMOTE_CONFIG_KEY = "config/config.yaml" | |
| REMOTE_AUTHS_PREFIX = "auths" | |
| STATE_PATH = Path(os.environ.get("OBJECTSTORE_SYNC_STATE_PATH", "") or (ROOT / ".objectstore-sync-state.json")) | |
| XAI_PROXY_URLS = parse_proxy_urls( | |
| os.environ.get("XAI_PROXY_URLS", "") or "socks5h://127.0.0.1:9" | |
| ) | |
| def mc_env() -> dict: | |
| env = os.environ.copy() | |
| for key in ("HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "http_proxy", "https_proxy", "all_proxy"): | |
| env.pop(key, None) | |
| return env | |
| MC_TIMEOUT = int(os.environ.get("MC_TIMEOUT", "30")) | |
| def run_mc(args: list[str], check: bool = True) -> subprocess.CompletedProcess[str]: | |
| return subprocess.run( | |
| [MC_BIN, *args], | |
| check=check, | |
| env=mc_env(), | |
| capture_output=True, | |
| text=True, | |
| timeout=MC_TIMEOUT, | |
| ) | |
| def ensure_alias() -> None: | |
| run_mc(["alias", "set", ALIAS, ENDPOINT, ACCESS_KEY, SECRET_KEY, "--api", "S3v4", "--path", "on"]) | |
| def remote_path(key: str) -> str: | |
| return f"{ALIAS}/{BUCKET}/{key}" | |
| def parse_ts(value: str) -> float: | |
| return datetime.fromisoformat(value.replace("Z", "+00:00")).timestamp() | |
| def local_path(rel: str) -> Path: | |
| return ROOT / rel | |
| def _is_auth_rel(rel: str) -> bool: | |
| return rel.startswith(f"{REMOTE_AUTHS_PREFIX}/") and len(rel) > len(REMOTE_AUTHS_PREFIX) + 1 | |
| def load_sync_state() -> tuple[set[str], dict[str, dict[str, str]]]: | |
| try: | |
| data = json.loads(STATE_PATH.read_text()) | |
| except (OSError, ValueError): | |
| return set(), {} | |
| if not isinstance(data, dict): | |
| return set(), {} | |
| raw_rels = data.get("known_rels") | |
| known_rels = {str(rel) for rel in raw_rels if isinstance(rel, str)} if isinstance(raw_rels, list) else set() | |
| derived: dict[str, dict[str, str]] = {} | |
| raw_derived = data.get("derived_from_remote") | |
| if isinstance(raw_derived, dict): | |
| for rel, value in raw_derived.items(): | |
| if not isinstance(rel, str) or not isinstance(value, dict): | |
| continue | |
| remote_etag = value.get("remote_etag") | |
| local_md5 = value.get("local_md5") | |
| if isinstance(remote_etag, str) and isinstance(local_md5, str): | |
| derived[rel] = { | |
| "remote_etag": remote_etag, | |
| "local_md5": local_md5, | |
| } | |
| return known_rels, derived | |
| def load_known_rels() -> set[str]: | |
| return load_sync_state()[0] | |
| def save_known_rels( | |
| inventory: dict[str, dict], | |
| derived_from_remote: dict[str, dict[str, str]] | None = None, | |
| ) -> None: | |
| derived = derived_from_remote or {} | |
| payload = { | |
| "version": 2, | |
| "updated_at": datetime.now(timezone.utc).isoformat(), | |
| "known_rels": sorted(inventory), | |
| "derived_from_remote": { | |
| rel: derived[rel] | |
| for rel in sorted(derived) | |
| if rel in inventory | |
| }, | |
| } | |
| STATE_PATH.parent.mkdir(parents=True, exist_ok=True) | |
| with NamedTemporaryFile( | |
| "w", | |
| encoding="utf-8", | |
| delete=False, | |
| dir=str(STATE_PATH.parent), | |
| ) as tmp: | |
| json.dump(payload, tmp, ensure_ascii=False, sort_keys=True) | |
| tmp.write("\n") | |
| tmp_path = Path(tmp.name) | |
| tmp_path.replace(STATE_PATH) | |
| def touch_local(path: Path, ts: float) -> None: | |
| os.utime(path, (ts, ts)) | |
| def prune_empty_dirs(root: Path) -> None: | |
| if not root.exists(): | |
| return | |
| for path in sorted((p for p in root.rglob("*") if p.is_dir()), reverse=True): | |
| try: | |
| path.rmdir() | |
| except OSError: | |
| pass | |
| def file_md5(path: Path) -> str: | |
| digest = hashlib.md5() | |
| with path.open("rb") as handle: | |
| while True: | |
| chunk = handle.read(1024 * 1024) | |
| if not chunk: | |
| break | |
| digest.update(chunk) | |
| return digest.hexdigest() | |
| def remote_inventory() -> dict[str, dict]: | |
| inventory: dict[str, dict] = {} | |
| config_proc = run_mc(["stat", "--json", remote_path(REMOTE_CONFIG_KEY)], check=False) | |
| if config_proc.returncode == 0 and config_proc.stdout.strip(): | |
| raw = json.loads(config_proc.stdout) | |
| inventory[REMOTE_CONFIG_KEY] = { | |
| "etag": raw["etag"], | |
| "last_modified": parse_ts(raw["lastModified"]), | |
| "remote": remote_path(REMOTE_CONFIG_KEY), | |
| } | |
| auths_proc = run_mc(["ls", "--json", "--recursive", remote_path(REMOTE_AUTHS_PREFIX)], check=False) | |
| if auths_proc.returncode == 0: | |
| for line in auths_proc.stdout.splitlines(): | |
| if not line.strip(): | |
| continue | |
| raw = json.loads(line) | |
| if raw.get("status") != "success" or raw.get("type") != "file": | |
| continue | |
| rel = f"{REMOTE_AUTHS_PREFIX}/{raw['key']}" | |
| inventory[rel] = { | |
| "etag": raw["etag"], | |
| "last_modified": parse_ts(raw["lastModified"]), | |
| "remote": remote_path(rel), | |
| } | |
| return inventory | |
| def local_inventory() -> dict[str, dict]: | |
| inventory: dict[str, dict] = {} | |
| config_path = local_path(REMOTE_CONFIG_KEY) | |
| if config_path.is_file(): | |
| inventory[REMOTE_CONFIG_KEY] = { | |
| "md5": file_md5(config_path), | |
| "mtime": config_path.stat().st_mtime, | |
| } | |
| auth_root = local_path(REMOTE_AUTHS_PREFIX) | |
| if auth_root.is_dir(): | |
| for path in sorted(auth_root.rglob("*")): | |
| if not path.is_file(): | |
| continue | |
| rel = path.relative_to(ROOT).as_posix() | |
| inventory[rel] = { | |
| "md5": file_md5(path), | |
| "mtime": path.stat().st_mtime, | |
| } | |
| return inventory | |
| def _enforce_downloaded_xai_proxy(path: Path, auth_name: str) -> bool: | |
| try: | |
| payload = json.loads(path.read_text(encoding="utf-8")) | |
| except (OSError, UnicodeDecodeError, json.JSONDecodeError): | |
| return False | |
| if not isinstance(payload, dict) or str(payload.get("type") or "").strip().lower() != "xai": | |
| return False | |
| desired_proxy = stable_proxy_for_auth(auth_name, XAI_PROXY_URLS) | |
| current_proxy = payload.get("proxy_url") | |
| current_proxy = current_proxy.strip() if isinstance(current_proxy, str) else "" | |
| changed = current_proxy != desired_proxy | |
| if changed: | |
| payload["proxy_url"] = desired_proxy | |
| path.write_text( | |
| json.dumps(payload, ensure_ascii=False, indent=2) + "\n", | |
| encoding="utf-8", | |
| ) | |
| path.chmod(0o600) | |
| return changed | |
| def download_file(rel: str, meta: dict) -> bool: | |
| dest = local_path(rel) | |
| dest.parent.mkdir(parents=True, exist_ok=True) | |
| with NamedTemporaryFile(delete=False, dir=str(dest.parent)) as temporary: | |
| temporary_path = Path(temporary.name) | |
| temporary_path.unlink() | |
| replaced = False | |
| try: | |
| run_mc(["cp", meta["remote"], str(temporary_path)]) | |
| changed = False | |
| if rel == REMOTE_CONFIG_KEY: | |
| changed = enforce_config_proxy_url(temporary_path) | |
| elif _is_auth_rel(rel): | |
| changed = _enforce_downloaded_xai_proxy(temporary_path, dest.name) | |
| touch_local(temporary_path, meta["last_modified"]) | |
| temporary_path.replace(dest) | |
| replaced = True | |
| finally: | |
| if not replaced and temporary_path.exists(): | |
| temporary_path.unlink() | |
| return changed | |
| def remember_derived_file( | |
| derived_from_remote: dict[str, dict[str, str]], | |
| rel: str, | |
| remote_etag: str, | |
| ) -> None: | |
| path = local_path(rel) | |
| derived_from_remote[rel] = { | |
| "remote_etag": remote_etag, | |
| "local_md5": file_md5(path), | |
| } | |
| def enforce_config_without_mtime_change(path: Path) -> bool: | |
| original_mtime = path.stat().st_mtime | |
| changed = enforce_config_proxy_url(path) | |
| if changed: | |
| touch_local(path, original_mtime) | |
| return changed | |
| def upload_file(rel: str) -> None: | |
| src = local_path(rel) | |
| if not src.is_file(): | |
| return | |
| run_mc(["cp", str(src), remote_path(rel)]) | |
| def delete_remote(rel: str) -> None: | |
| run_mc(["rm", "--force", remote_path(rel)], check=False) | |
| INVALID_STATUS_KEYWORDS = [ | |
| "token_invalidated", | |
| "token_revoked", | |
| "invalidated oauth token", | |
| "authentication token has been invalidated", | |
| "account has been deactivated", | |
| "no_organization", | |
| "unauthorized", | |
| "401", | |
| ] | |
| def _is_free_auth_file_name(file_name: str) -> bool: | |
| return file_name.strip().endswith("-free.json") | |
| def _free_auth_cleanup_enabled() -> bool: | |
| return os.environ.get("CLEANUP_ENABLED", "0").strip() == "1" | |
| def _fetch_invalid_auth_names() -> set[str]: | |
| """Query local CLIProxyAPI management API for invalid free auth names. | |
| Team auth lifecycle is managed externally; runtime sync must not evict team | |
| auths for transient states such as cooldown or temporary unavailability. | |
| """ | |
| if not _free_auth_cleanup_enabled(): | |
| return set() | |
| mgmt_key = os.environ.get("MANAGEMENT_PASSWORD") or os.environ.get("API_KEY") or "" | |
| port = os.environ.get("PORT", "8317") | |
| if not mgmt_key: | |
| return set() | |
| url = f"http://127.0.0.1:{port}/v0/management/auth-files" | |
| req = Request(url) | |
| req.add_header("Authorization", f"Bearer {mgmt_key}") | |
| try: | |
| with urlopen(req, timeout=10) as resp: | |
| data = json.loads(resp.read()) | |
| except (HTTPError, URLError, OSError, ValueError): | |
| return set() | |
| if not isinstance(data, dict): | |
| return set() | |
| files = data.get("files", []) | |
| if not isinstance(files, list): | |
| return set() | |
| invalid_names: set[str] = set() | |
| now = datetime.now(timezone.utc).isoformat() | |
| for entry in files: | |
| if not isinstance(entry, dict): | |
| continue | |
| name = str(entry.get("name") or "").strip() | |
| if not name: | |
| continue | |
| if not _is_free_auth_file_name(name): | |
| continue | |
| status = str(entry.get("status") or "").strip().lower() | |
| status_message = str(entry.get("status_message") or "").strip().lower() | |
| unavailable = entry.get("unavailable", False) | |
| # Check next_retry_after — if still in cooldown, treat as invalid | |
| next_retry = str(entry.get("next_retry_after") or "").strip() | |
| in_cooldown = bool(next_retry and next_retry > now) | |
| if status == "error" or unavailable or in_cooldown: | |
| invalid_names.add(name) | |
| continue | |
| if status_message: | |
| for kw in INVALID_STATUS_KEYWORDS: | |
| if kw in status_message: | |
| invalid_names.add(name) | |
| break | |
| return invalid_names | |
| def restore() -> None: | |
| ensure_alias() | |
| ROOT.mkdir(parents=True, exist_ok=True) | |
| local_path("config").mkdir(parents=True, exist_ok=True) | |
| shutil.rmtree(local_path(REMOTE_AUTHS_PREFIX), ignore_errors=True) | |
| local_path(REMOTE_AUTHS_PREFIX).mkdir(parents=True, exist_ok=True) | |
| remote = remote_inventory() | |
| derived_from_remote: dict[str, dict[str, str]] = {} | |
| if REMOTE_CONFIG_KEY in remote: | |
| if download_file(REMOTE_CONFIG_KEY, remote[REMOTE_CONFIG_KEY]): | |
| remember_derived_file( | |
| derived_from_remote, | |
| REMOTE_CONFIG_KEY, | |
| remote[REMOTE_CONFIG_KEY]["etag"], | |
| ) | |
| elif CONFIG_FALLBACK: | |
| fallback = Path(CONFIG_FALLBACK) | |
| if fallback.is_file(): | |
| target = local_path(REMOTE_CONFIG_KEY) | |
| target.parent.mkdir(parents=True, exist_ok=True) | |
| shutil.copy2(fallback, target) | |
| run_mc(["cp", "--recursive", remote_path(f"{REMOTE_AUTHS_PREFIX}/"), str(local_path(REMOTE_AUTHS_PREFIX))], check=False) | |
| for rel, meta in remote.items(): | |
| if not _is_auth_rel(rel): | |
| continue | |
| path = local_path(rel) | |
| if not path.is_file(): | |
| continue | |
| changed = _enforce_downloaded_xai_proxy(path, path.name) | |
| touch_local(path, meta["last_modified"]) | |
| if changed: | |
| remember_derived_file(derived_from_remote, rel, meta["etag"]) | |
| enable_codex_auth_websockets(local_path(REMOTE_AUTHS_PREFIX)) | |
| config_path = local_path(REMOTE_CONFIG_KEY) | |
| if config_path.is_file(): | |
| enforce_config_without_mtime_change(config_path) | |
| save_known_rels(local_inventory(), derived_from_remote) | |
| def sync() -> None: | |
| ensure_alias() | |
| ROOT.mkdir(parents=True, exist_ok=True) | |
| enable_codex_auth_websockets(local_path(REMOTE_AUTHS_PREFIX)) | |
| config_path = local_path(REMOTE_CONFIG_KEY) | |
| if config_path.is_file(): | |
| enforce_config_without_mtime_change(config_path) | |
| invalid_names = _fetch_invalid_auth_names() | |
| known_rels, derived_from_remote = load_sync_state() | |
| remote = remote_inventory() | |
| local = local_inventory() | |
| # Remote has, local doesn't: | |
| # - if this auth file was seen in a previous sync, local deletion wins | |
| # and we delete the remote mirror too. This makes management-UI DELETE | |
| # durable instead of letting the next sync resurrect the file. | |
| # - if it is genuinely new to this instance, download it. | |
| # Both have, md5 differs → compare mtime, newer wins (unless invalid) | |
| for rel, meta in remote.items(): | |
| # Extract auth file name from rel path (e.g. "auths/codex-xxx-free.json" → "codex-xxx-free.json") | |
| file_name = rel.rsplit("/", 1)[-1] if "/" in rel else rel | |
| if file_name in invalid_names: | |
| derived_from_remote.pop(rel, None) | |
| delete_remote(rel) | |
| dest = local_path(rel) | |
| if dest.is_file(): | |
| dest.unlink() | |
| continue | |
| local_meta = local.get(rel) | |
| if local_meta is None: | |
| if _is_auth_rel(rel) and rel in known_rels: | |
| derived_from_remote.pop(rel, None) | |
| delete_remote(rel) | |
| continue | |
| if download_file(rel, meta): | |
| remember_derived_file(derived_from_remote, rel, meta["etag"]) | |
| else: | |
| derived_from_remote.pop(rel, None) | |
| continue | |
| if local_meta["md5"] == meta["etag"]: | |
| derived_from_remote.pop(rel, None) | |
| continue | |
| derived = derived_from_remote.get(rel) | |
| if ( | |
| derived is not None | |
| and derived.get("remote_etag") == meta["etag"] | |
| and derived.get("local_md5") == local_meta["md5"] | |
| ): | |
| continue | |
| if local_meta["mtime"] > meta["last_modified"]: | |
| derived_from_remote.pop(rel, None) | |
| upload_file(rel) | |
| else: | |
| if download_file(rel, meta): | |
| remember_derived_file(derived_from_remote, rel, meta["etag"]) | |
| else: | |
| derived_from_remote.pop(rel, None) | |
| # Local has, remote doesn't → upload to remote (new file from management UI) | |
| for rel in sorted(set(local) - set(remote)): | |
| file_name = rel.rsplit("/", 1)[-1] if "/" in rel else rel | |
| if file_name in invalid_names: | |
| derived_from_remote.pop(rel, None) | |
| dest = local_path(rel) | |
| if dest.is_file(): | |
| dest.unlink() | |
| continue | |
| derived_from_remote.pop(rel, None) | |
| upload_file(rel) | |
| if config_path.is_file(): | |
| enforce_config_without_mtime_change(config_path) | |
| prune_empty_dirs(local_path(REMOTE_AUTHS_PREFIX)) | |
| save_known_rels(local_inventory(), derived_from_remote) | |
| def main() -> int: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("mode", choices=("restore", "sync")) | |
| args = parser.parse_args() | |
| if args.mode == "restore": | |
| restore() | |
| else: | |
| sync() | |
| return 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |