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
v1.9.52: catalog foreground contract
6 files changed
+22−12
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.51+1.9.52
CHANGELOG.md+9@@ -3,6 +3,15 @@ All notable changes to the Adom Bridge Fusion 360 bridge, newest first. Canonical: https://wiki.adom.inc/adom/fusion-bridge · GitHub backup: `adom-inc/fusion-bridge` +## 1.9.52 - 2026-08-16++- **The catalog now teaches the full foreground contract.** fusion_describe's foreground arg docs+ were stale after 1.9.51 (still "optional bool") - an AI following the catalog would hit the+ foreground_reason_required refusal and only learn from the error. All foreground-capable verbs+ now document the background default, the windowEtiquette response marker, and the exact+ {foreground:true, foregroundReason:"..."} shape with the 3s-caption semantics; the background+ annotation hint shows the same literal re-call shape.+ ## 1.9.51 - 2026-08-16 - **Foreground etiquette contract (John, after ab's demo stole his focus).** (1) The tour's
adom-bridge-fusion-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.51",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.51/adom-bridge-fusion-v1.9.51.zip",- "sha256": "916f14373464d461ab0e074c79849ef855f5c1bd22869d99359c829b995130f5",- "size": 398944,+ "version": "1.9.52",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.52/adom-bridge-fusion-v1.9.52.zip",+ "sha256": "eaa4e8f6383c10fdd90e007199eb1077d080e8371fdab5ff31b170cd58370c8a",+ "size": 399141, "verbPrefixes": [ "fusion_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.51",+ "version": "1.9.52", "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.",
describe.py+3−3@@ -197,9 +197,9 @@ _T = [ ("fusion_export_skp", "Export to SketchUp (.skp).", {"outputPath": "required str"}, {"format": "str"}, 300, None, True, {"outputPath": "C:/out/part.skp"}), # ── Library SHOW verbs + bare-artifact wrapping (issue #29, shipped 1.9.9) ──- ("fusion_show_symbol", "Open a schematic SYMBOL in Fusion's library editor - first-class, no hand-built EDIT strings. Pass name + libraryPath (.lbr, opened first; omit libraryPath if a library is already open), OR pass a BARE <symbol> XML fragment as symbolXml and the bridge generates a minimal wrapper library around it (deviceset + gate synthesized) so it shows in the Library Manager. Background-safe: never steals the foreground.", {"name": "str (deviceset/symbol name; optional if symbolXml carries name=)", "libraryPath": "optional str (WINDOWS path .lbr)", "symbolXml": "optional str (bare <symbol ...>...</symbol>)", "foreground": "optional bool - user's choice to WATCH; default background"}, {"success": "bool", "view": "str", "screenshot": "str path", "wrappedLibrary": "str (when wrapped)"}, 180, None, True, {"name": "ADS8588SIPM", "libraryPath": "C:/Temp/lib.lbr"}),- ("fusion_show_footprint", "Open a FOOTPRINT (package) in Fusion's library editor. Same contract as fusion_show_symbol: name + libraryPath, or a bare <package> fragment as packageXml (wrapper library generated).", {"name": "str", "libraryPath": "optional str", "packageXml": "optional str (bare <package ...>...</package>)", "foreground": "optional bool - user's choice to WATCH; default background"}, {"success": "bool", "view": "str", "screenshot": "str path", "wrappedLibrary": "str (when wrapped)"}, 180, None, True, {"name": "ADS8588SIPM", "libraryPath": "C:/Temp/lib.lbr"}),- ("fusion_show_3d_package", "Open the 3D CHIP view (Package3DEnvironment) for a library package - and the RELIABLE way to get a 3D model into a library: pass stepPath and it is attached AFTER the library opens (embedded <packages3d> in hand-built .lbr files is the Fusion quirk that fails; attach-after-open works). stepPath with no library/packageXml auto-generates a minimal 2-pad carrier footprint. Without stepPath it just enters the 3D view of the named package.", {"name": "str", "libraryPath": "optional str (.lbr)", "packageXml": "optional str (bare <package> fragment)", "stepPath": "optional str (WINDOWS path .step to attach)", "foreground": "optional bool - user's choice to WATCH; default background"}, {"success": "bool", "view": "str", "screenshot": "str path", "wrappedLibrary": "str"}, 300, None, True, {"name": "MYCHIP", "stepPath": "C:/Temp/chip.step"}),+ ("fusion_show_symbol", "Open a schematic SYMBOL in Fusion's library editor - first-class, no hand-built EDIT strings. Pass name + libraryPath (.lbr, opened first; omit libraryPath if a library is already open), OR pass a BARE <symbol> XML fragment as symbolXml and the bridge generates a minimal wrapper library around it (deviceset + gate synthesized) so it shows in the Library Manager. Background-safe: never steals the foreground.", {"name": "str (deviceset/symbol name; optional if symbolXml carries name=)", "libraryPath": "optional str (WINDOWS path .lbr)", "symbolXml": "optional str (bare <symbol ...>...</symbol>)", "foreground": "optional bool - DEFAULT IS BACKGROUND (no focus steal; response carries windowEtiquette:background). true REQUIRES foregroundReason and shows it to the user as a 3s ab caption before any focus change - only when the USER asked to watch", "foregroundReason": "required WITH foreground:true - a short user-facing sentence shown as the 3s caption (e.g. 'You asked to watch the 3D board build')"}, {"success": "bool", "view": "str", "screenshot": "str path", "wrappedLibrary": "str (when wrapped)"}, 180, None, True, {"name": "ADS8588SIPM", "libraryPath": "C:/Temp/lib.lbr"}),+ ("fusion_show_footprint", "Open a FOOTPRINT (package) in Fusion's library editor. Same contract as fusion_show_symbol: name + libraryPath, or a bare <package> fragment as packageXml (wrapper library generated).", {"name": "str", "libraryPath": "optional str", "packageXml": "optional str (bare <package ...>...</package>)", "foreground": "optional bool - DEFAULT IS BACKGROUND (no focus steal; response carries windowEtiquette:background). true REQUIRES foregroundReason and shows it to the user as a 3s ab caption before any focus change - only when the USER asked to watch", "foregroundReason": "required WITH foreground:true - a short user-facing sentence shown as the 3s caption (e.g. 'You asked to watch the 3D board build')"}, {"success": "bool", "view": "str", "screenshot": "str path", "wrappedLibrary": "str (when wrapped)"}, 180, None, True, {"name": "ADS8588SIPM", "libraryPath": "C:/Temp/lib.lbr"}),+ ("fusion_show_3d_package", "Open the 3D CHIP view (Package3DEnvironment) for a library package - and the RELIABLE way to get a 3D model into a library: pass stepPath and it is attached AFTER the library opens (embedded <packages3d> in hand-built .lbr files is the Fusion quirk that fails; attach-after-open works). stepPath with no library/packageXml auto-generates a minimal 2-pad carrier footprint. Without stepPath it just enters the 3D view of the named package.", {"name": "str", "libraryPath": "optional str (.lbr)", "packageXml": "optional str (bare <package> fragment)", "stepPath": "optional str (WINDOWS path .step to attach)", "foreground": "optional bool - DEFAULT IS BACKGROUND (no focus steal; response carries windowEtiquette:background). true REQUIRES foregroundReason and shows it to the user as a 3s ab caption before any focus change - only when the USER asked to watch", "foregroundReason": "required WITH foreground:true - a short user-facing sentence shown as the 3s caption (e.g. 'You asked to watch the 3D board build')"}, {"success": "bool", "view": "str", "screenshot": "str path", "wrappedLibrary": "str"}, 300, None, True, {"name": "MYCHIP", "stepPath": "C:/Temp/chip.step"}), ("fusion_demo_progress", "Poll a running fusion_demo tour: {percent, elapsedSec, estimatedSec, step, stepLabel, done, failed, shots, shotCount, stepShot}. Poll ~1-2.5s and render a REAL progress bar. LIVE EVIDENCE (issue #30): each frame MAY carry stepShot {step, title, image} - a ~640px base64 capture the BRIDGE took at that step's completion, one per step, riding the first frame after it completes (render these during the run; the page should not guess-snap). shots[] streams too: mid-run it carries paths for every completed step; pass imagesAs:base64 + sinceShot:<count you have> to receive only NEW shots fully encoded. done:true = the full gallery (base64 by default). Finished tours are DISK-SNAPSHOTTED, so the final frame stays pollable even across a bridge respawn.", {"demoId": "required str (from fusion_demo mode:tour; omitted = the single running tour)", "imagesAs": "optional str paths|base64|both", "sinceShot": "optional int - shots you already received; response windows to the new ones"}, {"percent": "int", "step": "str", "stepLabel": "str", "done": "bool", "shots": "list", "shotCount": "int", "stepShot": "dict|absent"}, 15, None, False, {"demoId": "tour-abc123", "imagesAs": "base64", "sinceShot": 3}), ("fusion_make_test_project", "Create a NEW electronics test project FROM SCRATCH around a library part - the Web Control demo's PROJECT button, and the answer to 'a customer only has a component page'. Generates a minimal test circuit server-side (the part + a generated 330R series resistor with VCC/GND stubs on a small board) as real EAGLE .sch/.brd, then imports the pair as a new electronics design. NO cloud, NO sign-in, no pre-existing content. After it, fusion_show_schematic / fusion_show_2d_board / fusion_show_3d_board all work on the result. Wiring uses the deviceset's own connects (first two pins), so 2-terminal parts get a real circuit and big ICs get a structurally-valid integration proof.", {"libraryPath": "required str (WINDOWS path .lbr; stage from container first)", "deviceset": "optional str (defaults to the library's first deviceset)"}, {"success": "bool", "schPath": "str", "brdPath": "str", "circuit": "str"}, 300, None, True, {"libraryPath": "C:/Temp/IN-S42ATR.lbr"}),
server.py+4−3@@ -7766,9 +7766,10 @@ def dispatch_command(command: str, args: dict, caller_identity: dict = None) -> # and the AI should not "helpfully" foreground anything afterward. if _ran_backgrounded and isinstance(res, dict): res.setdefault("windowEtiquette", "background")- note = ("Window opened/changed in the BACKGROUND - the user's focus was NOT touched. "- "Render results via fusion_state. Only pass foreground:true (with "- "foregroundReason) if the USER asked to watch.")+ note = ("Window opened/changed in the BACKGROUND - the user's focus was NOT touched; "+ "do NOT foreground anything to compensate. Render results via fusion_state. "+ "If the USER asks to watch, re-call with {\"foreground\": true, "+ "\"foregroundReason\": \"<why, shown to the user as a 3s caption>\"}.") h = res.get("_hint") res["_hint"] = (h + " " + note) if isinstance(h, str) and note not in h else (h or note) return res