← Commit history

Publish 1.9.244

John Lauer ·b366018042 ·1mo ago ·parent d43a384
3 files changed +60−11
.release-page-head+1−1
@@ -1 +1 @@-4a6ba8d45583b875254cf75fcb6de39039e54d26\ No newline at end of file+d43a384ff56772a655266e58a5d401f68268e13e\ No newline at end of file
page.json+7−10
@@ -11,10 +11,6 @@     "uninstall": "./uninstall.sh"   },   "tags": [-    "ab",-    "bridge",-    "fusion",-    "desktop-app",     "fusion360",     "autodesk",     "cad",@@ -79,10 +75,7 @@     "build a basic parts library",     "add a 3d model to a component",     "make a fusion 360 library with 3d",-    "set up the fusion bridge",-    "fusion dashboard",-    "fusion status page",-    "open the fusion launch page"+    "set up the fusion bridge"   ],   "discovery_pitch": "Use the Adom Bridge Fusion 360 bridge when the user wants to DRIVE Autodesk Fusion 360 from the cloud: open/search their team's Fusion cloud designs, lay out a PCB or do electronics, export STEP/IGES/STL/Gerbers/BOM, or build a component library with real rendering 3D. It runs Fusion on the user's own machine via Adom Bridge. NOT for web/browser/login/form-filling (that's the native-browser extension) and NOT for KiCad (that's the kicad bridge).",   "brief": "Drive Autodesk Fusion 360 from the cloud via Adom Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.",@@ -111,5 +104,9 @@       "label": "Part volume",       "prompt": "How much material does each printed part in this assembly use?"     }-  ]-}+  ],+  "author": {+    "name": "John Lauer",+    "email": "[email protected]"+  }+}\ No newline at end of file
tools/live_feed_drain.pyadded+52
@@ -0,0 +1,52 @@+#!/usr/bin/env python3+"""Drain fusion_live_feed's box-side ring buffer into shotlog, from the container.++    python3 tools/live_feed_drain.py --target AdomLapper --channel fusion-live [--interval 1.0]++Publishes each frame with a kind tag so a viewer never confuses them:+  [main #n]   the Fusion window each tick (the ~1 fps video)+  [popup #n.m] each owned dialog/panel over it, tied to its tick+Proof frames are NOT here; they come from fusion_prove_result evidence[] (kind:proof).+"""+import argparse, json, subprocess, sys, time, os, base64++def ab(target, verb, args):+    p = subprocess.run(["adom-bridge", "--ai-thread", "fusion-live-feed", "--target", target, verb, json.dumps(args)],+                       capture_output=True, text=True, timeout=90)+    try:+        d = json.loads(p.stdout); x = d.get("data") or d+        if isinstance(x.get("output"), str):+            try: x = json.loads(x["output"])+            except Exception: pass+        return x+    except Exception:+        return {}++def main():+    a = argparse.ArgumentParser(); a.add_argument("--target", required=True); a.add_argument("--channel", default="fusion-live")+    a.add_argument("--interval", type=float, default=1.0); a.add_argument("--max-sec", type=float, default=600)+    o = a.parse_args()+    st = ab(o.target, "fusion_live_feed", {"action": "start", "intervalSec": o.interval, "maxSec": o.max_sec})+    print("feed:", "started" if st.get("started") else ("already running" if st.get("alreadyRunning") else st))+    since, t0, pushed = 0, time.time(), 0+    os.makedirs("/tmp/live_feed", exist_ok=True)+    while time.time() - t0 < o.max_sec:+        r = ab(o.target, "fusion_live_feed", {"action": "frames", "since": since})+        for f in r.get("frames") or []:+            since = max(since, f["tick"])+            rf = ab(o.target, "read_file", {"path": f["path"], "encoding": "base64"})+            c = rf.get("content") or ""+            if not c: continue+            local = "/tmp/live_feed/%s_%d_%s.png" % (f["kind"], f["tick"], f.get("index", 0))+            try: open(local, "wb").write(base64.b64decode(c))+            except Exception: continue+            desc = ("[main #%d] %s | %d popup(s)" % (f["tick"], f.get("title", ""), f.get("popups", 0)) if f["kind"] == "main"+                    else "[popup #%d.%d] %s" % (f["tick"], f.get("index", 0), f.get("title", "")))+            subprocess.run(["adom-shotlog", "inject", "-c", o.channel, "-d", desc, "-s", "desktop_screenshot_window", "--native", local],+                           capture_output=True, text=True, timeout=30)+            pushed += 1+        if not r.get("running") and since: print("feed ended; pushed", pushed); break+        time.sleep(o.interval)+    ab(o.target, "fusion_live_feed", {"action": "stop"})++if __name__ == "__main__": main()