danmoreng's picture
Publish prebuilt MacroStories browser lab with WebGPU and WASM
6e74009 verified
Raw History Blame Contribute Delete
3.09 kB
"""Create/update the static demo Space using the user's local Hugging Face login."""
import argparse
import hashlib
import json
from pathlib import Path
import subprocess
import shutil
import tempfile
from huggingface_hub import HfApi
ROOT = Path(__file__).resolve().parents[1]
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--repo", default="danmoreng/macrostories-browser")
args = parser.parse_args()
api = HfApi()
try:
identity = api.whoami()
except Exception:
raise SystemExit("No working Hugging Face login. Run `uvx --from huggingface_hub hf auth login` locally, then retry.")
owner, name = args.repo.split("/", 1)
namespaces = {namespace.lower(): namespace for namespace in [identity["name"], *(org["name"] for org in identity.get("orgs", []))]}
if owner.lower() not in namespaces:
raise SystemExit(f"Logged in as {identity['name']}, but the requested destination belongs to {owner}.")
# Hub account URLs accept display casing, but repo creation requires the
# canonical account namespace returned by whoami (here: danmoreng).
args.repo = f"{namespaces[owner.lower()]}/{name}"
provenance = json.loads((ROOT / "models/macrostories/provenance.json").read_text())
model = ROOT / "models/macrostories/onnx/model.onnx"
if hashlib.sha256(model.read_bytes()).hexdigest() != provenance["onnx_sha256"]:
raise SystemExit("ONNX model checksum mismatch. Re-export and verify the model before deployment.")
subprocess.run(["npm", "run", "test"], cwd=ROOT, check=True)
subprocess.run(["npm", "run", "build"], cwd=ROOT, check=True)
api.create_repo(args.repo, repo_type="space", space_sdk="static", private=False, exist_ok=True)
# Static Space build commands require credits. Publish the already-built
# frontend directly, retaining readable sources alongside the runtime assets.
with tempfile.TemporaryDirectory(prefix="macrostories-space-") as directory:
staging = Path(directory)
for name in ["README.md", "LICENSE", "THIRD_PARTY_NOTICES.md", ".gitignore", "styles.css", "package.json", "package-lock.json", "requirements-export.txt"]:
shutil.copyfile(ROOT / name, staging / name)
for name in ["src", "scripts", "tests", "models", "third-party"]:
shutil.copytree(ROOT / name, staging / name, ignore=shutil.ignore_patterns("__pycache__", "*.pyc"))
shutil.copytree(ROOT / "dist/src", staging / "assets")
shutil.copytree(ROOT / "dist/vendor", staging / "vendor")
html = (ROOT / "dist/index.html").read_text().replace('./src/app.js', './assets/app.js')
(staging / "index.html").write_text(html)
api.upload_folder(
repo_id=args.repo, repo_type="space", folder_path=staging,
commit_message="Publish prebuilt MacroStories browser lab with WebGPU and WASM",
)
print(f"Uploaded: https://huggingface.co/spaces/{args.repo}")
print("Published prebuilt static assets; no paid remote build is required.")
if __name__ == "__main__":
main()