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
Update 15 file(s)
9 files changed
+61−28
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.211+1.9.212
adom-bridge-fusion-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.211",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.211/adom-bridge-fusion-v1.9.211.zip",- "sha256": "65c5ce5df068161dcab0644f8c73fd8b37811a873d67118cd978c4bbbd7c457f",- "size": 499587,+ "version": "1.9.212",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.212/adom-bridge-fusion-v1.9.212.zip",+ "sha256": "0b083f79d09c8007ae271509509eb691d3a37301260e858f72c5174abf407767",+ "size": 500144, "verbPrefixes": [ "fusion_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.211",+ "version": "1.9.212", "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.",
dashboard/Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "fusion-dashboard"-version = "1.9.211"+version = "1.9.212" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.211"+version = "1.9.212" edition = "2021" [dependencies]
install.sh+1−1@@ -21,7 +21,7 @@ echo "Installed fusion-bridge skills: $(ls "$PKG_DIR/skills" 2>/dev/null | tr '\ # binary (the three-artifact pattern: bridge zip -> ab, THIS pkg -> container skills + # this download, page media -> wiki). Per the wiki's PKG_VS_RELEASE policy, binaries are # platform-tagged RELEASE assets, never tarball content - the installer fetches them.-DASH_VERSION="1.9.211"+DASH_VERSION="1.9.212" DASH_URL="https://wiki.adom.inc/download/adom/fusion-bridge/${DASH_VERSION}/fusion-dashboard" DEST="" if [ -w /usr/local/bin ]; then DEST=/usr/local/bin
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.9.211",+ "version": "1.9.212", "type": "app", "description": "This package installs the bridge's SKILLS into your container so your AI knows how to drive it; Adom Bridge loads the bridge runtime itself from the release zip.", "dependencies": {
page.json+11−8@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.9.211",+ "version": "1.9.212", "type": "app", "description": "This package installs the bridge's SKILLS into your container so your AI knows how to drive it; Adom Bridge loads the bridge runtime itself from the release zip.", "dependencies": {@@ -11,6 +11,10 @@ "uninstall": "./uninstall.sh" }, "tags": [+ "ab",+ "bridge",+ "fusion",+ "desktop-app", "fusion360", "autodesk", "cad",@@ -75,7 +79,10 @@ "build a basic parts library", "add a 3d model to a component", "make a fusion 360 library with 3d",- "set up the fusion bridge"+ "set up the fusion bridge",+ "fusion dashboard",+ "fusion status page",+ "open the fusion launch page" ], "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.",@@ -104,9 +111,5 @@ "label": "Part volume", "prompt": "How much material does each printed part in this assembly use?" }- ],- "author": {- "name": "John Lauer",- "email": "[email protected]"- }-}+ ]+}
server.py+40−10@@ -10362,6 +10362,23 @@ def _count_3d_bodies() -> dict: def _handle_prove_library(fusion_info: dict, args: dict) -> dict:+ # INCREMENTAL EMISSION (page issue #60, 2026-08-26): the four frames are captured in+ # the order a library is actually assembled - symbol, footprint, 3D, then the ganged+ # view as the closing proof - but they used to be published only when this function+ # RETURNED, so a caller watched nothing for ~370s and then got all four at once. An+ # optional _onFrame callback (passed by the create_library chain, never over the relay)+ # publishes each artifact the instant it lands, so a poller assembles the bundle+ # progressively and sees the ganged view arrive last.+ _on_frame = args.get("_onFrame") if callable(args.get("_onFrame")) else None++ def _emit(entry):+ if _on_frame:+ try:+ _on_frame(entry)+ except Exception:+ pass+ return entry+ """PROVE a .lbr with the FOUR evidence images John specified (2026-08-21): 1. the symbol, full screen in the Symbol editor@@ -10411,10 +10428,10 @@ def _handle_prove_library(fusion_info: dict, args: dict) -> dict: ("footprint", "pac", "footprint-editor")): r = _show_library_view(want, suffix, lbr) if not r.get("success"):- evidence.append({"step": label, "view": view, "ok": False,- "error": str(r.get("error"))[:160]})+ evidence.append(_emit({"step": label, "view": view, "ok": False,+ "error": str(r.get("error"))[:160]})) continue- evidence.append(_prove_capture(label, view))+ evidence.append(_emit(_prove_capture(label, view))) # 3: the 3D editor. Only reachable when a real package3d is bound - with none, Fusion # shows its Placeholder, which is exactly the false pass this verb exists to prevent. if artifacts["package3d"]["present"]:@@ -10498,7 +10515,7 @@ def _handle_prove_library(fusion_info: dict, args: dict) -> dict: "viewport is not evidence of a 3D chip.") elif chk["bodies"] < 0: e3["bodiesUnverified"] = True- evidence.append(e3)+ evidence.append(_emit(e3)) # HAND THE APP BACK (deterministic-close rule): the f3d doc is render scratch # here; close it verified so stage 4 is not stranded in the wrong workspace. # Same upload gate as _close_bridge_doc_verified: closing over an in-flight@@ -10515,14 +10532,14 @@ def _handle_prove_library(fusion_info: dict, args: dict) -> dict: except Exception: pass else:- evidence.append({"step": "package3d", "view": "3d-editor", "ok": False,+ evidence.append(_emit({"step": "package3d", "view": "3d-editor", "ok": False, "error": "Could not open the bound f3d (%s): %s" % ( _p3d_urn[-30:] if _p3d_urn else "no urn",- str((opened3d or {}).get("error"))[:100])})+ str((opened3d or {}).get("error"))[:100])})) else:- evidence.append({"step": "package3d", "view": "3d-editor", "ok": False,+ evidence.append(_emit({"step": "package3d", "view": "3d-editor", "ok": False, "error": "No package3d bound - the 3D editor would only show Fusion's "- "grey Placeholder, which is not evidence."})+ "grey Placeholder, which is not evidence."})) # 4: the ganged Library Manager view - symbol, footprint, 3D and pin connections at once. # Stage 3 left the app in a DIFFERENT document/workspace, so re-enter the library first, # verified - EDIT fails with "Not in Electronics editor" otherwise (run be27c38d034e).@@ -10531,7 +10548,7 @@ def _handle_prove_library(fusion_info: dict, args: dict) -> dict: _ensure_library_active(lbr, timeout_s=45) r = _show_library_view(want, "dev", lbr) if r.get("success"):- evidence.append(_prove_capture("ganged", "library-manager"))+ evidence.append(_emit(_prove_capture("ganged", "library-manager"))) else: evidence.append({"step": "ganged", "view": "library-manager", "ok": False, "error": str(r.get("error"))[:160]})@@ -11191,11 +11208,24 @@ def _handle_create_library(fusion_info: dict, args: dict) -> dict: state.update(stage="failed", success=False); _save(); return _leave("bind") _enter("proving (four evidence frames)")+ # #60: publish each artifact THE MOMENT it lands, in assembly order+ # (symbol -> footprint -> 3d -> ganged), so a poller watches the bundle build+ # instead of waiting ~370s for all four. The frame carries its own label, so a+ # renderer can show what just arrived and which phase is running.+ def _publish_frame(entry):+ ev = state.setdefault("evidence", [])+ ev.append(entry)+ state["evidenceCount"] = len(ev)+ state["lastArtifact"] = entry.get("step")+ state["stageLabel"] = "captured %s (%d of 4)" % (entry.get("step"), len(ev))+ _save()+ prove = _handle_prove_library(fusion_info, { "libraryPath": target_lbr, "name": args.get("name"), # the bind just told us exactly which f3d holds the geometry - hand it on so # the 3D frame never depends on re-parsing the lbr for it- "f3dUrn": ((state.get("bind") or {}).get("wip_urn") or "")})+ "f3dUrn": ((state.get("bind") or {}).get("wip_urn") or ""),+ "_onFrame": _publish_frame}) _leave("prove") state.update(stage="done", success=bool(prove.get("proven")), verdict=("proven" if prove.get("proven") else "not_proven"),