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 104 file(s)
9 files changed
+69−38
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.343+1.9.344
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.343",+ "version": "1.9.344", "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.343"+version = "1.9.344" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.343"+version = "1.9.344" 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.343"+DASH_VERSION="1.9.344" 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.343",+ "version": "1.9.344", "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−27@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.9.343",+ "version": "1.9.344", "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,28 +111,5 @@ "label": "Part volume", "prompt": "How much material does each printed part in this assembly use?" }- ],- "agent_permissions": {- "allow_bash": [],- "allow": [- "adom-desktop-fusion-bridge read-only verbs (via the adom-bridge CLI): fusion_readiness, fusion_get_app_state, fusion_addin_status, fusion_check_dialogs - state queries; they change nothing.",- "adom-desktop-fusion-bridge read-only verbs: fusion_alerts (reads Fusion's own log for toasts), fusion_document_info, fusion_window_info, fusion_board_info, fusion_library_parts - inspect only.",- "adom-desktop-fusion-bridge read-only verbs: fusion_prove_result (a persisted run report), fusion_plan_library_import (report-only preflight), fusion_list_cloud_projects, fusion_describe.",- "adom-desktop-fusion-bridge evidence captures fusion_screenshot_fusion and fusion_capture_library_views read pixels and write local image files only."- ],- "soft_deny": [- "adom-desktop-fusion-bridge lifecycle verbs fusion_stop, fusion_kill, fusion_restart_for_addin close or kill the Fusion application - keep the human prompt.",- "adom-desktop-fusion-bridge fusion_install_fusion silently installs Autodesk Fusion on the user's machine.",- "adom-desktop-fusion-bridge fusion_cleanup_cloud_files deletes files from the user's Autodesk cloud hub.",- "adom-desktop-fusion-bridge managed-library verbs (fusion_managed_library_push/pull/create/link/unlink) publish to or overwrite the user's library.io libraries."- ],- "environment": [- "adom-desktop-fusion-bridge is the Fusion 360 bridge for Adom Bridge; its fusion_* verbs are invoked through the adom-bridge CLI and drive Autodesk Fusion on the user's own desktop.",- "adom-desktop-fusion-bridge desktop actions also pass Adom Bridge's own human-approval gate (caller identity, per-call reason, Activity Log) - a container approval is the first of two gates."- ]- },- "author": {- "name": "John Lauer",- "email": "[email protected]"- }-}+ ]+}
server.py+32−5@@ -9608,6 +9608,17 @@ _TOUR_EXPLAIN = { # onto the tour's existing transport flags (paused / skipNext / replayPrev / abort), the # same ones fusion_demo_control sets, so the dashboard's buttons and the desktop remote # drive one mechanism and can be used interchangeably mid-tour.+#+# ⛔ ONE CONSUMER PER PANEL ID. `poll` DRAINS the press queue. Proven live 2026-09-03: a+# CLI `desktop_demo_panel {action:"poll"}` fired from a terminal to "check" the panel ate+# the user's PAUSE press, the panel flipped its face to paused, and the tour - the real+# consumer - never saw it. Verify a remote-driven tour ONLY through fusion_demo_progress+# (remotePresses / paused), never by polling the panel yourself.+#+# Presses are drained by a background ticker every ~2s for the whole tour (below), so a+# press lands in the flags immediately and the panel's face stays in sync; the tour still+# HONORS the flags only at step boundaries, never mid-verb (a verb in flight cannot be+# interrupted safely, and a half-finished Fusion op is worse than a late pause). _TOUR_PANEL_ID = "fusion-tour" @@ -9774,8 +9785,24 @@ def _orchestrate_demo_tour(args: dict) -> dict: done_est = 0 _docs_before_tour = _open_doc_names() # tour hygiene: close only what WE open _stop_labels = [s[1] for s in steps]+ _pump_stop = threading.Event() if remote: _tour_panel_show(state, _stop_labels, 0, playing=True)++ def _pump_loop():+ # Continuous drain (see the ONE CONSUMER note above). Re-shows the panel+ # only when the paused face changed, so the panel is not redrawn every tick.+ last_face = None+ while not _pump_stop.is_set():+ seen = _tour_panel_pump(state)+ face = bool(state.get("paused"))+ if seen or face != last_face:+ _tour_panel_show(state, _stop_labels, max(0, _step_ref[0] - 1),+ playing=not face)+ last_face = face+ _pump_stop.wait(2.0)+ _step_ref = [0]+ threading.Thread(target=_pump_loop, daemon=True, name="fusion-tour-remote").start() try: _VIEW_STEPS = {"symbol", "footprint", "device", "schematic", "2d-board", "3d-board", "library"} _last_view_step = None@@ -9784,17 +9811,16 @@ def _orchestrate_demo_tour(args: dict) -> dict: key, label, dur = steps[_step_i] _step_i += 1 # ── TRANSPORT (fusion_demo_control + the on-screen remote): boundary- # checks, never mid-verb. The remote's presses are drained here and while- # paused, onto the same flags the dashboard's buttons set. ──+ # checks, never mid-verb. The remote's presses are drained continuously by+ # the ticker onto the same flags the dashboard's buttons set; here we only+ # advance the panel's stop counter and honor the flags. ── if remote:- _tour_panel_pump(state)+ _step_ref[0] = _step_i _tour_panel_show(state, _stop_labels, _step_i - 1, playing=not state.get("paused")) if state.pop("abort", None): raise RuntimeError("tour exited by the user (transport control)") while state.get("paused") and not state.get("abort"): state.update(stepLabel="Paused - press play to continue", stepCaption="Paused.")- if remote:- _tour_panel_pump(state) time.sleep(1.5) if state.pop("abort", None): raise RuntimeError("tour exited by the user (transport control)")@@ -10091,6 +10117,7 @@ def _orchestrate_demo_tour(args: dict) -> dict: except Exception: pass if remote:+ _pump_stop.set() _tour_panel_hide() _demo_tour_persist(state)
skills/fusion-demo/SKILL.md+20@@ -162,3 +162,23 @@ Full flow: **fusion-onboarding**. - Nothing to open -> ask which board, or `fusion_aps_search` and open the first hit. - Never end a demo on an error screen. If a stage fails, say what you tried, and offer the next thing.++## The on-screen remote (from 1.9.343): `fusion_demo {mode:"tour", preset:"electronics", remote:true}`++`remote:true` makes the tour show ab's floaty glass transport panel (`desktop_demo_panel`,+id `fusion-tour`) with the tour's stops, and drain its PLAY / PAUSE / NEXT / BACK / STOP+presses onto the same flags `fusion_demo_control` sets, so the dashboard buttons and the+desktop remote can be mixed mid-tour. `preset:"electronics"` is the eight-stop showcase+John asked for: library import, symbol, footprint, 3D chip, ganged component view, a+schematic with that part, the 2D board, the 3D board (measured 2026-09-03: 247s, 9 frames,+zero failures on ConfRoomROG).++**⛔ Never poll the panel yourself.** `desktop_demo_panel {action:"poll", id:"fusion-tour"}`+DRAINS the press queue, and the tour is the consumer. A CLI poll fired "to check" ate the+user's PAUSE press live: the panel flipped to paused, the tour never saw it. Verify a+remote-driven tour ONLY through `fusion_demo_progress` (`remotePresses`, `paused`, `step`).++Presses are recorded immediately (a 2s ticker) but HONORED only at step boundaries, never+mid-verb: a Fusion operation in flight cannot be interrupted safely. So a pause pressed+during the 60s test-project generation takes effect when that step finishes. The caption+and the progress stream say "Paused - press play to continue" once it does.