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 8 file(s)
8 files changed
+72−19
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.87+1.9.88
adom-bridge-fusion-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.87",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.100/adom-bridge-fusion-v1.9.87.zip",- "sha256": "d1cf665859da8d1dacb67ac60d2e9b7d36dca5cea945197473025448a5188a48",- "size": 425140,+ "version": "1.9.88",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.101/adom-bridge-fusion-v1.9.88.zip",+ "sha256": "6099e2b6d130fe7a6edca8ed4c7749ae479196bc8bcc13956e0ee303897a38af",+ "size": 426021, "verbPrefixes": [ "fusion_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.87",+ "version": "1.9.88", "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.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.100"+version = "1.9.101" 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.100"+DASH_VERSION="1.9.101" 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.100",+ "version": "1.9.101", "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,16 +1,20 @@ { "slug": "fusion-bridge",- "version": "1.9.100",+ "version": "1.9.101", "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": {- "adom/adom-desktop": "*"+ "adom/adom-desktop": "^1.9.0" }, "scripts": { "install": "./install.sh", "uninstall": "./uninstall.sh" }, "tags": [+ "ab",+ "bridge",+ "fusion",+ "desktop-app", "fusion360", "autodesk", "cad",@@ -70,7 +74,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.",@@ -99,9 +106,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+52−2@@ -535,6 +535,26 @@ def _handle_new_electronics_from_eagle(args: dict) -> dict: } ++def _addin_round_trip_ready(tries: int = 2, gap: float = 1.5) -> bool:+ """Can the add-in actually EXECUTE a command, twice in a row?++ The distinction that issue #36 turned on: a listening socket proves the add-in's HTTP+ thread is up, not that Fusion's main thread will run our command. get_app_state is the+ cheapest real round-trip, so it is the honest readiness test.+ """+ import time as _t+ for i in range(tries):+ try:+ if not _proxy_to_addin("get_app_state", {}, timeout=6).get("success"):+ return False+ except Exception:+ return False+ if i + 1 < tries:+ _t.sleep(gap)+ return True++ def _handle_launch(fusion_info: dict, args: dict) -> dict: """Launch Fusion 360 and optionally wait for the AdomBridge add-in.""" # LIVE detect (not the stale bridge-start fusion_info snapshot) so a launch right@@ -648,7 +668,17 @@ def _handle_launch(fusion_info: dict, args: dict) -> dict: _t.sleep(1.0) continue # No seat dialog -> is the add-in actually serving? (ground truth for drivable)- if _probe_addin(timeout=1.5):+ #+ # ⚠️ A PORT THAT ANSWERS IS NOT AN ADD-IN THAT CAN WORK (page issue #36, found by+ # ralph-testing the web-control page): `_probe_addin` proves a socket replied, and+ # this verb's own hint promises it "blocks until the add-in is ready". A caller+ # reasonably took that at face value, fired the next verb, and got "add-in not+ # responding" - three surface buttons failed in that window, and minutes later the+ # identical calls worked. So require a REAL command round-trip (get_app_state, the+ # cheapest thing the add-in actually executes on its main thread), and require it+ # TWICE: the first success can land while the add-in is still finishing startup,+ # and one more tick is far cheaper than handing the caller a false ready.+ if _probe_addin(timeout=1.5) and _addin_round_trip_ready(): addin_ok = True # Give the human a window worth looking at (background, no activation). try:@@ -1570,6 +1600,26 @@ def _handle_fusion_readiness(fusion_info: dict, args: dict) -> dict: "fusion_install_fusion (no shell approval needed) - it streams the free trial and " "this verb reports installing:true until done.") + # READY MUST MEAN DRIVABLE (page issue #36). `addin_ok` above comes from an HTTP GET to+ # the add-in's own web server, which is served by its HTTP thread - it is up well before+ # Fusion's MAIN thread will execute a command. Callers poll this verb precisely to learn+ # "can I fire my next verb now", so confirm with one real round-trip before saying yes.+ # Cheap when the main thread is free (~50ms); when it is not, failing here is exactly the+ # answer the caller needed.+ if ready:+ try:+ if not _proxy_to_addin("get_app_state", {}, timeout=4).get("success"):+ ready = False+ result_note = ("the add-in's HTTP server is up but its main thread did not "+ "execute a test command yet - not drivable this second")+ else:+ result_note = None+ except Exception:+ ready = False+ result_note = "the add-in did not complete a test command round-trip"+ else:+ result_note = None+ result = { "success": True, "hostApp": "Fusion 360",@@ -1579,7 +1629,7 @@ def _handle_fusion_readiness(fusion_info: dict, args: dict) -> dict: "ready": ready, "bridgeVersion": BRIDGE_VERSION, **stale_info,- "_hint": hint,+ "_hint": (hint + " NOTE: " + result_note) if result_note else hint, } # MEASURED PROGRESS WHILE LAUNCHING (issue #32): the poll verb must render the same # bar the launch verb started, or the caller is back to a spinner with no end.