app
Fusion - the Fusion 360 Bridge
Public Made by Adomby adom
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.
← Commit history
v1.9.36: recursive coordMap
4 files changed
+36−10
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.35+1.9.36
adom-bridge-fusion-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.35",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.35/adom-bridge-fusion-v1.9.35.zip",- "sha256": "081b01b18ad4946e098e796f1641507ae40aad25239573072a425f477fa2ba84",- "size": 383740,+ "version": "1.9.36",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.36/adom-bridge-fusion-v1.9.36.zip",+ "sha256": "e9c44a4aef4179d46bda5ace301990e4bb343cddd8214ffa37bf7e27363999e1",+ "size": 384038, "verbPrefixes": [ "fusion_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.35",+ "version": "1.9.36", "description": "Drive Autodesk Fusion 360 from the cloud: launch Fusion, electronics board layout, design rules, exports (STEP/IGES/STL/3MF/USDZ/OBJ/DXF/DWG/Gerbers/BOM/CPL), fast APS server-indexed cloud search plus browse/recent/file-info/versions, cloud file download/upload and folder creation, and in-app parametric modeling (fusion_run_modeling_script). Never-charge: APS calls are capped to the free tier.", "homepage": "https://wiki.adom.inc/adom/fusion-bridge", "author": "Adom Inc.",
server.py+30−4@@ -4951,6 +4951,32 @@ def _unwrap(r): return r +def _find_coordmap(obj, depth=0):+ """Recursively find a coordMap (with shotId) anywhere in a verb response - ab has+ moved it across envelope levels between versions (top-level sibling of data in some,+ nested under data in others, stringified inside output in 2.0.46's direct API).+ Returns the coordMap dict or {}."""+ if depth > 5:+ return {}+ if isinstance(obj, str) and obj[:1] in "[{":+ try:+ import json as _j+ return _find_coordmap(_j.loads(obj), depth + 1)+ except Exception:+ return {}+ if isinstance(obj, dict):+ cm = obj.get("coordMap")+ if isinstance(cm, dict) and cm.get("shotId"):+ return cm+ if obj.get("shotId"):+ return obj+ for k in ("data", "output", "result", "response"):+ got = _find_coordmap(obj.get(k), depth + 1)+ if got:+ return got+ return {}++ def _fusion_click_signin() -> dict: """Click Fusion's 'Welcome to Fusion' -> Sign In button SERVER-SIDE, ALWAYS, on the user's behalf (John, 2026-07-22: "you should ALWAYS just click sign in on behalf of the adom@@ -4975,10 +5001,10 @@ def _fusion_click_signin() -> dict: _raw = _ad_call("desktop_screenshot_window", {"hwnd": int(hwnd)}, timeout=45) shot = _unwrap(_raw)- # coordMap lives at the TOP level of the response, BESIDE data - _unwrap alone loses it- # (this exact miss broke the server-side Sign In click twice, 2026-08-16).- cm = shot.get("coordMap") or (_raw.get("coordMap") if isinstance(_raw, dict) else None) or {}- sid = cm.get("shotId") or shot.get("shotId") or (_raw.get("shotId") if isinstance(_raw, dict) else None)+ # ab has moved coordMap across envelope levels between versions (sibling of data /+ # nested / stringified in output on 2.0.46) - search recursively, never guess a level.+ cm = _find_coordmap(_raw)+ sid = cm.get("shotId") if not sid: return {"clicked": False, "why": "screenshot returned no shotId (hwnd=%s raw_keys=%s err=%s)" % (