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.6.76: hard-disable crashing in-app cloud search, APS readiness guard + rich hints, ABE sign-in skill
7 files changed
+170−20
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.6.75+1.6.76
adom-bridge-fusion-manifest.json+5−5@@ -1,13 +1,13 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.6.75",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.75/adom-bridge-fusion-v1.6.75.zip",- "sha256": "20beea4addf440e2892d30f35bdc9b15072b0e27c617ca5d5bd3b337e2d70bbc",- "size": 379941,+ "version": "1.6.76",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.76/adom-bridge-fusion-v1.6.76.zip",+ "sha256": "85728d1dd5098d66a6b60e9b03787bd4bfc1063174922695ce2c85b8e44ab173",+ "size": 15238076, "verbPrefixes": [ "fusion_" ], "healthEndpoint": "/status",- "released_at": "2026-07-07T16:20:00Z"+ "released_at": "2026-07-16T12:05:26Z" }
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.6.75",+ "version": "1.6.76", "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/adom-desktop-fusion-bridge", "author": "Adom Inc.",
describe.py+4−4@@ -76,10 +76,10 @@ _T = [ {"projectId": "required str", "parentFolderId": "required str", "name": "required str"}, {"folderId": "str"}, 50, None, False, {"projectId": "a.YnVz...", "parentFolderId": "urn:...", "name": "Adom AI Workspace"}), ("fusion_aps_get", "Raw authenticated GET against a free APS path (dev/verify helper).", {"path": "required str"}, {"status": "int", "body": "obj"}, 40, None, False, {"path": "/project/v1/hubs"}),- ("fusion_walk_cloud_tree", "DO NOT USE: slow in-app add-in walk (30+ min) that CAN CRASH Fusion (WinError 10054). Use fusion_aps_search instead; see the 'fusion-aps-search' skill.",- {}, {"tree": "obj"}, 600, _STATUS, True, {}),- ("fusion_search_cloud_files", "DO NOT USE: slow in-app add-in search (30+ min) that CAN CRASH Fusion (WinError 10054). Use fusion_aps_search instead; see the 'fusion-aps-search' skill.",- {"query": "required str"}, {"results": "[...]"}, 180, _STATUS, True, {"query": "Molecule"}),+ ("fusion_walk_cloud_tree", "⛔ DISABLED (returns an error): the in-app add-in walk took 30+ min and CRASHED Fusion (WinError 10054). It is hard-blocked in the bridge. Use fusion_aps_search / fusion_aps_open. See the 'fusion-aps-search' skill.",+ {}, {"disabled": "bool"}, 15, None, False, {}),+ ("fusion_search_cloud_files", "⛔ DISABLED (returns an error): the in-app add-in search took 30+ min and CRASHED Fusion (WinError 10054). It is hard-blocked in the bridge. Use fusion_aps_search {query} — server-indexed, seconds, no Fusion. See the 'fusion-aps-search' skill.",+ {"query": "required str"}, {"disabled": "bool"}, 15, None, False, {"query": "Molecule"}), # ── Electronics ──────────────────────────────────────────────────────── ("fusion_show_schematic", "Switch the OPEN electronics design to its SCHEMATIC view (the symmetric partner of fusion_show_2d_board / fusion_show_3d_board, via Fusion's SwitchSchDocCmd). A VIEW of the project, not a standalone file. Drive it for demos with fusion_electron_zoom / _pan / _select.",
server.py+103−9@@ -1560,6 +1560,94 @@ def _handle_get_preferences(fusion_info: dict, args: dict) -> dict: return _shape_pref_result(res, wrote=False) +# ── APS state + AI hint builder ───────────────────────────────────────────────+# Every cloud-file path routes through APS now (the old in-app search is disabled —+# see _handle_deprecated_cloud_search). This helper reads live APS state and returns+# a rich, self-teaching hint bundle so the AI ALWAYS knows: is APS installed/configured?+# signed in? token live/expired? what the verbs are, that it must sign in, and that the+# best sign-in path is the user's NATIVE Chrome/Edge via ABE (adom-browser-extension).+_APS_VERB_MAP = (+ "fusion_aps_status (state) · fusion_aps_signin (sign in) · fusion_aps_search {query} · "+ "fusion_aps_open {name} · fusion_aps_browse · fusion_aps_recent · fusion_aps_file_info · "+ "fusion_aps_versions · fusion_aps_download · fusion_aps_upload · fusion_aps_create_folder · "+ "fusion_aps_set_browser/get_browser/forget_browser (remember the native browser+profile)"+)+_APS_WHY = (+ "WHY APS: Autodesk offers NO fast file-search API for Fusion. The only in-app option "+ "(walk/search the folder tree from the add-in) takes 30+ min and CAN CRASH Fusion "+ "(WinError 10054). We searched far and wide; APS (Autodesk Platform Services, server-indexed) "+ "is the ONLY thing that works — seconds, no Fusion needed, no crash. It needs a one-time "+ "OAuth sign-in; once set up it is fast and amazing. The old crashing search is now DISABLED."+)+_APS_ABE = (+ "BEST sign-in path: drive the user's OWN Chrome/Edge (already logged into Autodesk) via ABE "+ "(adom-browser-extension). If ABE is not installed, tell the user to install it first "+ "(wiki.adom.inc/adom/adom-browser-extension), then walk them through it. With ABE the bridge "+ "opens the Autodesk auth URL in their real signed-in profile and captures the token — no "+ "password typing. Fallback: fusion_aps_signin {allowDefaultBrowser:true}."+)+++def _aps_state_hint(extra: str = "") -> dict:+ """Live APS readiness + a self-teaching hint bundle for the AI. Never raises."""+ try:+ st = aps.handle_status({})+ d = st.get("data", {}) if isinstance(st, dict) else {}+ except Exception as e: # pragma: no cover - defensive+ d = {"error": str(e)}+ configured = bool(d.get("configured"))+ signed_in = bool(d.get("signedIn"))+ live = bool(d.get("tokenLive"))+ if not configured:+ stage, todo = "not_configured", ("Register a PKCE app at https://aps.autodesk.com (Data "+ "Management API on), then fusion_aps_set_client_id + fusion_aps_signin.")+ elif not signed_in:+ stage, todo = "not_signed_in", "Sign in: fusion_aps_signin (prefer ABE / native browser)."+ elif not live:+ stage, todo = "token_expired", "Token expired/refresh failed — fusion_aps_signin again."+ else:+ stage, todo = "ready", "Ready — fusion_aps_search {\"query\":\"...\"} or fusion_aps_open {\"name\":\"...\"}."+ parts = [f"APS {stage}.", todo, "VERBS: " + _APS_VERB_MAP, _APS_ABE, _APS_WHY]+ if extra:+ parts.insert(0, extra)+ return {+ "apsStage": stage, "apsConfigured": configured, "apsSignedIn": signed_in,+ "apsTokenLive": live, "_hint": " ".join(parts),+ }+++def _aps_guarded(fn, args: dict):+ """Run an APS cloud handler, but FIRST ensure APS is signed-in + token-live. If not,+ short-circuit with the rich self-teaching hint bundle (state + verbs + sign-in + ABE)+ so the AI knows exactly what to do instead of getting an opaque auth failure. This is+ the 'check every time, in code' guard the user asked for."""+ state = _aps_state_hint()+ if state["apsStage"] != "ready":+ return {+ "success": False,+ "error": f"APS is {state['apsStage']} — sign in before cloud file operations.",+ "output": state["apsStage"],+ "data": {"apsNotReady": True, **state},+ "_hint": state["_hint"],+ }+ return fn(args)+++def _handle_deprecated_cloud_search(command: str, args: dict) -> dict:+ """HARD-BLOCK the old in-app cloud search/walk (crashes Fusion). Redirect to APS,+ surfacing live APS state so the AI can immediately continue via the good path."""+ aps_state = _aps_state_hint()+ return {+ "success": False,+ "error": (f"fusion_{command} is DISABLED: the in-app Fusion cloud "+ "search/walk takes 30+ min and CAN CRASH Fusion (WinError 10054). "+ "Use fusion_aps_search {\"query\":\"...\"} (or fusion_aps_open to open by name) instead."),+ "output": "deprecated_cloud_search_disabled",+ "data": {"disabled": True, "use": "fusion_aps_search", **aps_state},+ "_hint": aps_state["_hint"],+ }++ COMMAND_HANDLERS = { "describe": lambda fi, args: describe.handle_describe(args), "readiness": _handle_fusion_readiness,@@ -1610,16 +1698,22 @@ COMMAND_HANDLERS = { "aps_set_browser": lambda fi, args: aps.handle_set_browser(args), "aps_get_browser": lambda fi, args: aps.handle_get_browser(args), "aps_forget_browser": lambda fi, args: aps.handle_forget_browser(args),- "aps_search": lambda fi, args: aps.handle_search(args),- "aps_browse": lambda fi, args: aps.handle_browse(args),- "aps_recent": lambda fi, args: aps.handle_recent(args),- "aps_file_info": lambda fi, args: aps.handle_file_info(args),- "aps_versions": lambda fi, args: aps.handle_versions(args),- "aps_download": lambda fi, args: aps.handle_download(args),- "aps_create_folder": lambda fi, args: aps.handle_create_folder(args),- "aps_upload": lambda fi, args: aps.handle_upload(args),- "aps_open": lambda fi, args: _handle_aps_open(fi, args),+ # Cloud-data verbs go through _aps_guarded: it checks signed-in + token-live EVERY call+ # and returns the rich APS hint bundle (state/verbs/sign-in/ABE) if not ready.+ "aps_search": lambda fi, args: _aps_guarded(aps.handle_search, args),+ "aps_browse": lambda fi, args: _aps_guarded(aps.handle_browse, args),+ "aps_recent": lambda fi, args: _aps_guarded(aps.handle_recent, args),+ "aps_file_info": lambda fi, args: _aps_guarded(aps.handle_file_info, args),+ "aps_versions": lambda fi, args: _aps_guarded(aps.handle_versions, args),+ "aps_download": lambda fi, args: _aps_guarded(aps.handle_download, args),+ "aps_create_folder": lambda fi, args: _aps_guarded(aps.handle_create_folder, args),+ "aps_upload": lambda fi, args: _aps_guarded(aps.handle_upload, args),+ "aps_open": lambda fi, args: _aps_guarded(lambda a: _handle_aps_open(fi, a), args), "aps_get": lambda fi, args: aps.handle_get(args),+ # DEPRECATED cloud search — HARD-BLOCKED here (in COMMAND_HANDLERS) so they return+ # BEFORE ever reaching the crashing add-in path. Redirect to APS + surface APS state.+ "search_cloud_files": lambda fi, args: _handle_deprecated_cloud_search("search_cloud_files", args),+ "walk_cloud_tree": lambda fi, args: _handle_deprecated_cloud_search("walk_cloud_tree", args), }
skills/fusion-aps-search/SKILL.md+25@@ -116,3 +116,28 @@ for cloud search, ever — no matter how blocked you feel. 3. **AUTH-001 "client_id does not have access to the api product":** the APS app at aps.autodesk.com/myapps lost its **Data Management API** product. Open the app → API Access → ensure Data Management API is checked → **Save changes** → wait a few minutes to propagate → retry.++## UPDATE (John, 2026-07-16): the old in-app search is now HARD-DISABLED in code++`fusion_search_cloud_files` and `fusion_walk_cloud_tree` no longer run. The bridge intercepts+them in `COMMAND_HANDLERS` (`_handle_deprecated_cloud_search`) and returns an error that+redirects to `fusion_aps_search`, together with live APS state. They can NO LONGER crash Fusion,+because they never reach the add-in. Do not try to "fall back" to them: there is nothing to fall+back to. APS is the only cloud-search path.++## Auto-guard: APS readiness is checked in CODE on every cloud call++Every cloud-data verb (`aps_search/open/browse/recent/file_info/versions/download/upload/+create_folder`) is wrapped by `_aps_guarded` in server.py. It checks signed-in + token-live+BEFORE the call and, if not ready, returns the rich hint bundle from `_aps_state_hint`+(stage + verb map + sign-in instruction + the ABE native-browser suggestion + WHY-APS). So the+AI never gets an opaque auth failure — it always gets the next step. Surface that `_hint` to the+user verbatim.++## Apologize, then reassure (the honest framing for the user)++If a user hits the one-time APS setup, be honest: "Autodesk offers NO fast file-search API for+Fusion. The only in-app option walks the folder tree and takes 30+ minutes and can crash Fusion.+We searched far and wide; APS (server-indexed) is the only thing Autodesk offers that actually+works. Sorry it needs a one-time sign-in, but once it's set up it's fast and genuinely great."+Then get them set up (prefer ABE native-browser sign-in, see fusion-aps-signin).
skills/fusion-aps-signin/SKILL.md+31@@ -271,3 +271,34 @@ portal is fragile and Edge crashes):** and the bridge's listener captures the token. 5. Poll `fusion_aps_status` until `signedIn:true`. Done — APS search is fast and never touches Fusion's main thread.++## The BEST sign-in path: the user's NATIVE Chrome/Edge via ABE (adom-browser-extension)++Autodesk's OTP/2FA and its "which profile is signed in" problem vanish if we drive the user's+OWN browser that is ALREADY logged into Autodesk. That is what ABE (adom-browser-extension) is+for: it exposes `nbrowser_*` verbs that open a URL in the user's real Chrome/Edge profile.++**Recommend ABE first, and hand-hold the install if it's missing:**+1. Check: does `adom-desktop --target <laptop> nbrowser_readiness '{}'` succeed? If not, ABE isn't+ installed.+2. Tell the user (honestly): "The smoothest Autodesk sign-in drives your own Chrome/Edge that's+ already logged in, no password typing, no OTP races. That needs the Adom Browser Extension+ (ABE). Let me walk you through installing it, one time."+3. Point them to the install: https://wiki.adom.inc/adom/adom-browser-extension and follow the+ `installing-the-extension` steps (load the MV3 extension, approve the native-host). Do as much+ as you can drive for them; only ask for the clicks Chrome forces a human to make.+4. Once ABE is live: `fusion_aps_signin` returns `needsExtensionOpen` with an `authUrl`; open it+ via `nbrowser_open_window` in their signed-in profile; the bridge's localhost listener captures+ the token; poll `fusion_aps_status` until `signedIn:true`. Then `fusion_aps_set_browser {how:+ "extension"}` so every future sign-in reuses that exact profile.++Fallback only if ABE truly can't be installed: `fusion_aps_signin {allowDefaultBrowser:true}`+(OS default browser) and drive the OTP per this skill.++## Say the honest WHY (apologize, then reassure)++Autodesk gives no fast Fusion file-search API; the only in-app option takes 30+ minutes and can+crash Fusion, so it's now disabled. APS (server-indexed) is the one thing that works. The cost is+a one-time OAuth sign-in. Tell the user that plainly, apologize for the friction, and reassure+them: once it's set up, cloud search is instant and it stays signed in (auto-refresh). It is+worth it.