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
+87−18
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.209+1.9.210
adom-bridge-fusion-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.209",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.209/adom-bridge-fusion-v1.9.209.zip",- "sha256": "ca5e84bea81f7b19ab79383ace76d1cde8f43d4bf067dabb9f42e270e3972b12",- "size": 497196,+ "version": "1.9.210",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.210/adom-bridge-fusion-v1.9.210.zip",+ "sha256": "0ab6a51068cbf739be7563627a747e464b704bc8818e1b9b9de1a806a44965f2",+ "size": 499221, "verbPrefixes": [ "fusion_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.209",+ "version": "1.9.210", "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.209"+version = "1.9.210" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.209"+version = "1.9.210" 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.209"+DASH_VERSION="1.9.210" 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.209",+ "version": "1.9.210", "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.209",+ "version": "1.9.210", "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+66@@ -9094,6 +9094,40 @@ def _orchestrate_make_test_project(args: dict) -> dict: return out +def _sweep_untitled_scratch(max_close: int = 24) -> list:+ """Close UNMODIFIED 'Untitled' scratch documents (page issue #59, 2026-08-26).++ The library/bind flow left ~5 Untitled docs per import - 16 after three - and no+ caller could clear them, because close_all_documents skipped every Untitled. They are+ scratch by construction: an UNMODIFIED Untitled has no data file and no edits, so+ closing one cannot lose anything. Modified ones are never touched here; those may hold+ real unsaved work and need an explicit force. Fusion keeps a single blank doc alive on+ its own, which is the 'keep exactly one' the reporter asked for.+ """+ closed = []+ try:+ for _ in range(max_close):+ st = _proxy_to_addin("document_info", {}, timeout=8)+ docs = (st.get("data") or {}).get("openDocuments") or []+ victim = next((d for d in docs+ if str(d.get("name") or "").lower().startswith("untitled")+ and not (d.get("isModified") or d.get("modified"))), None)+ if not victim:+ break+ r = _proxy_to_addin("close_document",+ {"name": victim.get("name"), "save": False}, timeout=20)+ if not r.get("success"):+ break # stop on the first refusal rather than spin+ closed.append(str(victim.get("name")))+ if closed:+ print("[Fusion Bridge] swept %d Untitled scratch doc(s): %s"+ % (len(closed), ", ".join(closed[:6])))+ _bridge_action_ledger("untitled_scratch_swept", {"count": len(closed)})+ except Exception:+ pass+ return closed++ def _orchestrate_bind_library_3d(args: dict) -> dict: """ONE CALL for the correct library (John's bar: the 3D renders in the Content Manager): mint the part's 3D as a cloud f3d, inject the wip_urn binding into the@@ -9183,7 +9217,11 @@ def _orchestrate_bind_library_3d(args: dict) -> dict: "above); the prove stage opens the library itself, so the chain " "continues. If prove's 3D frame is missing, the library just needs a " "clean re-open once Fusion is idle." % urn)}+ # #59: the mint spawns scratch Untitled docs. Clear them before returning so a batch+ # caller's workspace stays bounded instead of growing ~5 docs per import.+ _swept = _sweep_untitled_scratch() return {"success": True, "wip_urn": urn, "mutatedInput": True,+ "untitledScratchClosed": len(_swept), "prebindBackup": lbr_path + ".prebind", "libraryPath": lbr_path, "deviceset": deviceset, "bound": True, "reopened": True,@@ -11233,6 +11271,34 @@ def _handle_action_ledger(args: dict) -> dict: COMMAND_HANDLERS["action_ledger"] = lambda info, args: _handle_action_ledger(args or {}) +def _handle_reset_workspace(args: dict) -> dict:+ """fusion_reset_workspace - bring Fusion back to a clean slate between runs (#59).++ Closes named documents AND the Untitled scratch the library/bind flow leaves behind,+ which close_all_documents alone could not do. Unmodified scratch always; MODIFIED+ Untitled docs only with force:true, because those can hold real unsaved work.+ """+ force = bool(args.get("force", False))+ r = dispatch_command("close_all_documents",+ {"save": False, "closeUntitled": True, "force": force})+ swept = _sweep_untitled_scratch()+ left = []+ try:+ st = _proxy_to_addin("document_info", {}, timeout=8)+ left = [d.get("name") for d in ((st.get("data") or {}).get("openDocuments") or [])]+ except Exception:+ pass+ return {"success": True, "closedByAddin": (r.get("data") or {}).get("closed"),+ "skipped": (r.get("data") or {}).get("skipped"),+ "untitledScratchClosed": len(swept), "remaining": left,+ "_hint": ("Fusion always keeps ONE blank document alive, so a single Untitled "+ "remaining is correct, not a failure. A modified Untitled is left "+ "untouched unless you pass force:true - it may hold unsaved work.")}+++COMMAND_HANDLERS["reset_workspace"] = lambda info, args: _handle_reset_workspace(args or {})++ def _handle_check_3d_thumbnail(fusion_info: dict, args: dict) -> dict: """Is the Library Manager's 3D THUMBNAIL actually rendered? Deterministic, no pixels.