from __future__ import annotations import base64 import io import time from typing import Any from urllib import error, request import numpy as np from constitutional_constants import LAMBDA, OMEGA, PHI, QBEC_VERSION, SIGMA from shared.serialization import safe_json_dumps from shared.tosp_protocol import build_header def sync_to_space(base_url: str, state: dict[str, Any], weights: np.ndarray, retries: int = 3) -> dict[str, Any]: buffer = io.BytesIO() np.save(buffer, weights, allow_pickle=False) payload = safe_json_dumps( { "state": state, "weights_b64": base64.b64encode(buffer.getvalue()).decode("utf-8"), }, indent=2, ).encode("utf-8") header = build_header(state["gnostic"], state["rdod"], state["frac"], state["node_id"], state) headers = { "Content-Type": "application/json", "X-QBEC-Constitutional-Gate": header.decode("utf-8"), "X-QBEC-Version": QBEC_VERSION, "X-QBEC-Lambda": LAMBDA, "X-QBEC-Omega": str(OMEGA), "X-QBEC-Sigma": str(SIGMA), } result = {"ok": False, "attempts": 0, "preview": ""} for attempt in range(1, retries + 1): result["attempts"] = attempt req = request.Request(f"{base_url.rstrip('/')}/sync", data=payload, headers=headers, method="POST") try: with request.urlopen(req, timeout=10) as response: result["ok"] = True result["preview"] = response.read().decode("utf-8", errors="replace")[:500] return result except Exception as exc: result["preview"] = str(exc) if attempt < retries: time.sleep(0.5 * (PHI ** attempt)) return result