Spaces:
Running on Zero
Running on Zero
| """Live smoke test against the deployed Space — one plan per granularity. | |
| Run after every Space sync: | |
| .venv/bin/python scripts/smoke_live.py [space_id] | |
| Needs an authenticated `hf` CLI (the token buys ZeroGPU quota; anonymous quota | |
| is often zero). Exits non-zero if any granularity fails to produce a plan. | |
| Gotcha baked in below: over the API the plan rows come back in the BrowserState | |
| output (res[3]["plan"]["rows"]) — the visible rows_state slot (res[0]) is empty. | |
| """ | |
| from __future__ import annotations | |
| import sys | |
| import time | |
| import huggingface_hub | |
| from gradio_client import Client | |
| SPACE = sys.argv[1] if len(sys.argv) > 1 else "build-small-hackathon/unstuck" | |
| TASK = "Clean up my inbox and reply to the important emails" | |
| EMPTY_DATA = {"records": [], "plan": None} | |
| # Looser than schema bounds on purpose: this checks the live pipeline produces | |
| # a sane plan, not that every model whim is in spec. | |
| EXPECTED = { | |
| "chunky": {"steps": (2, 8), "max_minutes": 25}, | |
| "regular": {"steps": (3, 12), "max_minutes": 25}, | |
| "tiny": {"steps": (3, 12), "max_minutes": 10}, | |
| } | |
| def main() -> int: | |
| token = huggingface_hub.get_token() | |
| if not token: | |
| print("FAIL: no HF token (run `hf auth login`)") | |
| return 1 | |
| client = Client(SPACE, token=token, verbose=False) | |
| failures = 0 | |
| for granularity, bounds in EXPECTED.items(): | |
| t0 = time.time() | |
| try: | |
| res = client.predict(TASK, EMPTY_DATA, granularity, api_name="/break_down") | |
| except Exception as exc: # noqa: BLE001 - report and keep testing the rest | |
| print(f"{granularity}: FAIL call error {type(exc).__name__}: {exc}") | |
| failures += 1 | |
| continue | |
| elapsed = time.time() - t0 | |
| plan = (res[3] or {}).get("plan") or {} | |
| rows = plan.get("rows") or [] | |
| lo, hi = bounds["steps"] | |
| problems = [] | |
| if not lo <= len(rows) <= hi: | |
| problems.append(f"{len(rows)} steps, wanted {lo}-{hi}") | |
| bad_minutes = [ | |
| r["raw_minutes"] | |
| for r in rows | |
| if not 0 < int(r.get("raw_minutes", 0)) <= bounds["max_minutes"] | |
| ] | |
| if bad_minutes: | |
| problems.append(f"raw_minutes out of bounds: {bad_minutes}") | |
| if any(not str(r.get("text", "")).strip() for r in rows): | |
| problems.append("empty step text") | |
| status = "FAIL " + "; ".join(problems) if problems else "OK" | |
| mins = [r.get("raw_minutes") for r in rows] | |
| print(f"{granularity}: {status} — {len(rows)} steps in {elapsed:.1f}s, minutes={mins}") | |
| failures += bool(problems) | |
| return 1 if failures else 0 | |
| if __name__ == "__main__": | |
| sys.exit(main()) | |