Spaces:
Runtime error
Runtime error
File size: 7,986 Bytes
afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 c3fc85f afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 c3fc85f afe3546 c3fc85f 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 c3fc85f afe3546 6b09b49 afe3546 c3fc85f afe3546 6b09b49 afe3546 c3fc85f 6b09b49 afe3546 6b09b49 afe3546 6b09b49 afe3546 6b09b49 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | """Capture beat driver β drive the live app through the demo beats deterministically.
This does NOT record video itself. Use it alongside Cap desktop, or point
scripts.record.py at an existing Chrome CDP endpoint. The script walks the UI
slowly with deliberate pauses while YOU (or cap-cli) capture the screen.
The UI tabs are LOAD Β· SLICE Β· PRINT Β· REVIEW. Selectors prefer stable IDs
over visible text wherever possible, so renames are less likely to break this
script than the previous text-only version.
One-time setup (local; not a Space/runtime dep):
uv pip install playwright && uv run playwright install chromium
Run the app first in another terminal:
make run # http://localhost:7860 (pre-warm one analyze!)
Then walk the beats (headed browser; record it with Cap):
uv run python -m scripts.capture --beat all
uv run python -m scripts.capture --beat 3 # load-bearing beat
uv run python -m scripts.capture --beat benchy # LOAD + Benchy quick-load
uv run python -m scripts.capture --beat loop # the learning loop
Options:
--url Space or local URL (default: https://node.microfactory.space)
--slowmo ms between Playwright actions (default 350)
--pause seconds between beats (default 1.5)
--headless hide the browser (no recording)
"""
from __future__ import annotations
import argparse
import sys
import time
def _pill(page, value):
"""Click an LCARS pill. CSS uppercases the text, but the DOM keeps the raw
value (part types are lowercase; materials are uppercase). Match the <label>
by its real text, scoped to pill groups."""
page.locator(".ce-pills label", has_text=value).first.click()
def _open_override(page):
"""Open the OVERRIDE ENVIRONMENT popup if it is not already open.
Idempotent: checks the popup's visibility before toggling."""
try:
popup = page.locator("#ce-popup-override")
if not popup.is_visible():
page.locator("#ce-override").first.click()
time.sleep(0.3)
except Exception:
pass
def _close_override(page):
"""Click the popup close button if it is open."""
try:
popup = page.locator("#ce-popup-override")
if popup.is_visible():
page.locator("#ce-popup-override .ce-popup-close").first.click()
time.sleep(0.2)
except Exception:
pass
def _set_sensors(page, t, h):
"""Set ambient Β°C + humidity %RH inside the override popup."""
nums = page.locator("#ce-popup-override .ce-num input")
try:
nums.nth(0).fill(str(t)); nums.nth(0).dispatch_event("change")
nums.nth(1).fill(str(h)); nums.nth(1).dispatch_event("change")
except Exception:
pass
def _load_benchy(page, slow):
"""Shared helper: LOAD tab β quick-load Benchy."""
page.get_by_role("tab", name="LOAD").click(); time.sleep(slow)
page.locator("#ce-benchy").first.click()
time.sleep(1.5)
def beat_load(page, slow):
"""Beat 3a β define the job in LOAD (empty start β quick-load a part +
material; set deterministic environment for a repeatable, risk-relevant take)."""
page.get_by_role("tab", name="LOAD").click(); time.sleep(slow)
_open_override(page); _set_sensors(page, 28, 60) # warm + humid β precedent-rich
_close_override(page)
_pill(page, "PLA"); time.sleep(slow)
page.locator("#ce-benchy").first.click()
time.sleep(2.0) # part preview (3D model) settles
def beat_benchy(page, slow):
"""LOAD + the 3DBenchy quick-load (the recognizable hero part)."""
page.get_by_role("tab", name="LOAD").click(); time.sleep(slow)
page.locator("#ce-benchy").first.click()
time.sleep(3.0) # watch the hull preview settle
def beat_slice(page, slow):
"""Beat 3b β SLICE: auto-switch to SLICE, let the engineer's read land."""
page.locator("#ce-run").first.click()
time.sleep(5.0) # reasoning + settings readout appear
def beat_second_opinion(page, slow):
"""The QA Inspector's pre-print critique on the SLICE page."""
page.locator("input[type=radio][value='Second Opinion']").first.check()
time.sleep(3.0)
def beat_scrub(page, slow):
"""Slide through the filled cross-section layers (on the SLICE page)."""
sl = page.locator("input[type=range]").last
for v in (8, 18, 30, 40):
sl.fill(str(v)); sl.dispatch_event("input"); sl.dispatch_event("change")
time.sleep(0.9)
def beat_placement(page, slow):
"""Plate-position beat β ABS in the corner: warp predicted + 'center it' suggestion."""
page.get_by_role("tab", name="LOAD").click(); time.sleep(slow)
_pill(page, "ABS") # high-shrink material
_open_override(page)
_pill(page, "corner") # worst plate position
_close_override(page)
page.locator("#ce-benchy").first.click()
time.sleep(slow)
page.locator("#ce-run").first.click()
time.sleep(5.0) # PLACEMENT risk + suggested alignment appear
def beat_print_single(page, slow):
"""Beat 4a β go to PRINT, run one print (deterministic) + inspector grade."""
page.get_by_role("tab", name="PRINT").click(); time.sleep(slow)
page.locator("#ce-print-run, #ce-print").first.click()
time.sleep(3.0)
def beat_print_loop(page, slow):
"""Beat 4b β PRINT: run iterations, quality climbs fail->clean with inspector grades."""
page.get_by_role("tab", name="PRINT").click(); time.sleep(slow)
page.locator("#ce-print-run, #ce-print").first.click()
time.sleep(5.0) # the curve fills in
def beat_review(page, slow):
"""Beat 4c β REVIEW: the ledger where lessons accumulate + the run verdict."""
page.get_by_role("tab", name="REVIEW").click()
time.sleep(3.0)
BEATS = {
"load": [beat_load],
"benchy": [beat_benchy],
"3": [beat_load, beat_slice],
"scrub": [beat_load, beat_slice, beat_scrub],
"second": [beat_load, beat_slice, beat_second_opinion],
"placement": [beat_placement, beat_scrub],
"4": [beat_print_single, beat_print_loop, beat_review],
"loop": [beat_print_loop, beat_review],
"review": [beat_review],
"all": [beat_load, beat_slice, beat_second_opinion, beat_scrub,
beat_placement, beat_print_single, beat_print_loop, beat_review],
}
def main() -> None:
ap = argparse.ArgumentParser(description="Walk the demo beats for screen capture.")
ap.add_argument("--beat", default="all", choices=sorted(BEATS), help="which beat(s) to walk")
ap.add_argument("--url", default="https://node.microfactory.space")
ap.add_argument("--slowmo", type=int, default=350, help="ms between Playwright actions")
ap.add_argument("--pause", type=float, default=1.5, help="seconds between beats")
ap.add_argument("--headless", action="store_true", help="hide the browser (no recording)")
args = ap.parse_args()
try:
from playwright.sync_api import sync_playwright
except ImportError:
sys.exit("playwright not installed β run: uv pip install playwright && uv run playwright install chromium")
print(f"Walking beat '{args.beat}' against {args.url} β start your Cap recording now.")
time.sleep(2.0)
slow = args.slowmo / 1000.0
with sync_playwright() as p:
browser = p.chromium.launch(headless=args.headless, slow_mo=args.slowmo)
page = browser.new_page(viewport={"width": 1600, "height": 1000})
page.goto(args.url + "/?__theme=dark", wait_until="domcontentloaded")
time.sleep(2.5)
for step in BEATS[args.beat]:
print(f" β {step.__name__}")
step(page, slow)
time.sleep(args.pause)
print("done β stop the recording. (browser stays open 5s)")
time.sleep(5.0)
browser.close()
if __name__ == "__main__":
main()
|