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
+90−22
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.215+1.9.216
adom-bridge-fusion-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.215",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.215/adom-bridge-fusion-v1.9.215.zip",- "sha256": "85a4fb31b22106da4bba7120da1312a8c87da3b967694a77216763219637f1e7",- "size": 505688,+ "version": "1.9.216",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.216/adom-bridge-fusion-v1.9.216.zip",+ "sha256": "2503c3bc281c832b597237d64b8cf10ef8b8729b7aa372afedf4e49ebd15c7f9",+ "size": 506828, "verbPrefixes": [ "fusion_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.215",+ "version": "1.9.216", "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.215"+version = "1.9.216" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.215"+version = "1.9.216" 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.215"+DASH_VERSION="1.9.216" 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.215",+ "version": "1.9.216", "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.215",+ "version": "1.9.216", "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+69−4@@ -4220,6 +4220,61 @@ def _handle_dismiss_blocking_dialogs(fusion_info: dict, args: dict) -> dict: COMMAND_HANDLERS["dismiss_blocking_dialogs"] = _handle_dismiss_blocking_dialogs +def _capture_3d_view(pkg: str, lbr_path: str, settle: float) -> dict:+ """Capture the DEDICATED 3D-package render as its own artifact (page issue #63).++ The 3D chip previously existed only as a thumbnail inside the ganged component view.+ Getting it standalone meant a separate fusion_show_3d_package call that re-attaches the+ STEP and re-renders - measured at a 180s timeout during the import campaign, and it+ took Fusion down with it under concurrent load. The 3D body is already built and saved+ by the time captures run, so entering the Package3D environment and photographing it is+ cheap: no re-attach, no re-render.+ """+ import time as _t+ entry = {"package": pkg, "view": "3d", "path": None, "ok": False}+ # A PLACEHOLDER IS NOT A RESULT (page issue #42). With no <package3d> bound, Fusion+ # renders a grey slab that photographs exactly like a real chip. Knowable offline.+ if lbr_path:+ try:+ if not _library_artifact_names(lbr_path).get("p3d"):+ entry.update({+ "errorCode": "no_3d_package_bound",+ "error": "No <package3d> is bound in that library, so the only thing to "+ "photograph is Fusion's grey Placeholder - refusing to return "+ "that as the 3D artifact.",+ "_hint": "Run fusion_build_library_3d (or fusion_bind_library_3d) first, "+ "then re-capture. A Placeholder looks like a successful 3D view "+ "in a screenshot, which is why this refuses instead."})+ return entry+ except Exception:+ pass+ cp = _create_3d_package(lbr_path, timeout=60) if lbr_path else {"success": False,+ "error": "no libraryPath"}+ if not cp.get("success"):+ entry.update({"errorCode": "create_3d_package_failed",+ "error": "Could not enter the Package3D environment: %s"+ % str(cp.get("error"))[:200]})+ return entry+ try:+ if settle:+ _t.sleep(settle)+ entry["path"] = _capture_labeled("%s_3d" % pkg)+ entry["ok"] = bool(entry["path"])+ finally:+ # ALWAYS leave the Package3D environment, even if the capture threw. Staying in it+ # would make every LATER view capture the 3D editor - exactly the mislabelled-frame+ # failure reported in page issue #62.+ try:+ _proxy_to_addin("execute_text_command", {"command": "Package3DStop"}, timeout=20)+ _t.sleep(0.6)+ _d = _dismiss_dialogs_bg()+ if _d:+ print("[Fusion Bridge] Package3DStop raised a dialog (%s) - answered in the "+ "background; see skills/fusion-no-modal-dialogs" % _d)+ except Exception as _e:+ print("[Fusion Bridge] Package3DStop failed: %s" % _e)+ return entry+ def _orchestrate_capture_library_views(args: dict) -> dict: """Capture the LIBRARY-EDITOR views that make EEs trust a part: the schematic SYMBOL, the FOOTPRINT (pads + layer stack), and the COMPONENT/device view (Content Manager: the symbol +@@ -4244,10 +4299,15 @@ def _orchestrate_capture_library_views(args: dict) -> dict: return {"success": False, "error": "packages: [<deviceset name>] (or package: <name>) required.", "_hint": "Open the .lbr first (fusion_open_lbr). Names are the deviceset names, e.g. ESP32-S3FN8."}- view_ext = {"component": "dev", "symbol": "sym", "footprint": "pac",- "dev": "dev", "sym": "sym", "pac": "pac"}- label_of = {"dev": "component", "sym": "symbol", "pac": "footprint"}- views = args.get("views") or ["component", "symbol", "footprint"]+ # FOUR artifacts, in ASSEMBLY ORDER (page issues #60 and #63): symbol, footprint,+ # the dedicated 3D chip, then the ganged component view LAST as the closing proof.+ # The 3D chip used to exist only as a thumbnail inside the ganged view, so a caller+ # could not show it as its own artifact without a separate fusion_show_3d_package call+ # that re-attaches the STEP - slow (180s timeout observed) and crash-prone under load.+ view_ext = {"component": "dev", "symbol": "sym", "footprint": "pac", "3d": "3d",+ "dev": "dev", "sym": "sym", "pac": "pac", "p3d": "3d", "package3d": "3d"}+ label_of = {"dev": "component", "sym": "symbol", "pac": "footprint", "3d": "3d"}+ views = args.get("views") or ["symbol", "footprint", "3d", "component"] # EDIT is async - the editor takes a beat to actually SWITCH the view. Capturing too soon grabs # the PREVIOUS view (a mislabeled shot). Settle AFTER the EDIT (before fit/capture); tunable. settle = float(args.get("settle", 1.5))@@ -4287,6 +4347,8 @@ def _orchestrate_capture_library_views(args: dict) -> dict: for pkg in pkgs: for v in views: ext = view_ext.get(v, v)+ if ext == "3d":+ continue # not an EDIT target; guarded by its own p3d check r, err = _resolve_artifact_name(pkg, ext, lbr_path) if err: name_errors.append({"package": pkg, "view": label_of.get(ext, ext),@@ -4299,6 +4361,9 @@ def _orchestrate_capture_library_views(args: dict) -> dict: for pkg in pkgs: for v in views: ext = view_ext.get(v, v)+ if ext == "3d":+ out.append(_capture_3d_view(pkg, lbr_path, settle))+ continue if lbr_path and (pkg, ext) not in resolved_names: # Would have prompted. Report it as a skip; do NOT hand it to Fusion. _bad = next((e for e in name_errors