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.43: dev skill + hints updated to UIA seat-dialog handling; narrate launch state
6 files changed
+52−23
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.6.42+1.6.43
CHANGELOG.md+11@@ -3,6 +3,17 @@ All notable changes to the Adom Desktop Fusion 360 bridge, newest first. Canonical: https://wiki.adom.inc/adom/adom-desktop-fusion-bridge · GitHub backup: `adom-inc/adom-desktop-fusion-bridge` +## 1.6.43 - 2026-07-06++- **Docs + hints caught up to the real (UIA) seat-dialog handling.** The `fusion-bridge-dev` skill now+ records the hard facts: it's a QT dialog (not CEF), titled just "Fusion360", its "Continue" button is+ UIA-invokable in the BACKGROUND, the radios are NOT in the a11y tree, kill+relaunch never frees a+ server-held seat (dead code), retry-until-verified-gone, and the seat check outranks a stale add-in+ port. Response hints now NARRATE what the bridge is doing + what happens next: `fusion_start` says it+ launched in the background (don't foreground), whether it auto-resolved a seat dialog, and to poll+ `fusion_readiness`; the readiness `licensingDialog` hint describes the UIA auto-resolve (not the old+ "free it from peer machines" text).+ ## 1.6.42 - 2026-07-06 - **Seat-resolve now RETRIES until the dialog is verified gone, and takes priority over a stale add-in
adom-bridge-fusion-manifest.json+5−5@@ -1,13 +1,13 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.6.42",- "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.42/adom-bridge-fusion-v1.6.42.zip",- "sha256": "19b1f290128591fed964570ab8f57be5eefcd2b04287e274672d4ad08a6d5104",- "size": 340876,+ "version": "1.6.43",+ "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.43/adom-bridge-fusion-v1.6.43.zip",+ "sha256": "0920a84b437d82db0ec91496439369ccad20e745e2af32692d35f0e7322221a7",+ "size": 341813, "verbPrefixes": [ "fusion_" ], "healthEndpoint": "/status",- "released_at": "2026-07-06T13:47:22Z"+ "released_at": "2026-07-06T13:52:37Z" }
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.6.42",+ "version": "1.6.43", "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.",
server.py+15−9@@ -247,12 +247,17 @@ def _handle_launch(fusion_info: dict, args: dict) -> dict: "recoveryFilesRelocated": reloc["moved"], "resolvedPath": fusion_info.get("exe_path", ""), "seatDialogResolved": _seat_clicks > 0,+ "backgroundLaunch": True, "_hint": (- ("Auto-resolved a seat/licensing dialog in the background (UIA, no foreground). "- if _seat_clicks else "")- + "Fusion is LAUNCHING but the add-in isn't up yet - a FIRST launch / a fresh "- "sign-in can take 2-4 min. This is NOT a failure and NOT a timeout to retry: do NOT "- "re-call fusion_start. POLL fusion_readiness until ready:true, then drive."+ "Fusion was launched IN THE BACKGROUND (minimized, foreground-lock on) so it does not "+ "steal the user's focus - do NOT foreground it. "+ + ("A seat 'Active Sessions Exceeded' dialog appeared and was AUTO-RESOLVED in the "+ "background via UIA (no foreground). " if _seat_clicks else "")+ + "The add-in isn't up yet - a first launch / fresh sign-in can take 2-4 min. This is "+ "NOT a failure and NOT a retry-able timeout: do NOT re-call fusion_start. WHAT HAPPENS "+ "NEXT: POLL fusion_readiness every ~10s; it returns needsSignin/licensingDialog/updating "+ "if something is mid-flight (the bridge handles the seat dialog itself), and ready:true "+ "when it is drivable - then run your fusion_* verbs." ), } @@ -895,10 +900,11 @@ def _handle_fusion_readiness(fusion_info: dict, args: dict) -> dict: elif ready: hint = "READY - drive Fusion (fusion_open_lbr / build_library_3d / etc.)." elif installed and running and licensing:- hint = ("Fusion is blocked by a SEAT/LICENSING dialog (e.g. 'Active Sessions Exceeded') - "- "detected by owning process + dialog size, NOT by title. Call fusion_start: it "- "AUTO-RECLAIMS the seat (frees it from peer machines, then relaunches clean). No user "- "action needed - this is not a crash.")+ hint = ("Fusion is blocked by a SEAT/LICENSING dialog ('Active Sessions Exceeded') - detected "+ "by owning process + dialog size (its title is just 'Fusion360'). fusion_start "+ "AUTO-RESOLVES it in the BACKGROUND by UIA-invoking its 'Continue' button (no "+ "foreground, no user action) and retries until it clears. If you see this persist, just "+ "call fusion_start again - it is not a crash, and never coordinate-click or ask the user.") elif installed and running: hint = ("Fusion is RUNNING but its add-in is NOT responding yet - NOT ready to drive. Either it " "is still finishing launch / signing in (poll fusion_readiness a few more times), or the "
skills/fusion-bridge-dev/SKILL.md+19−7@@ -62,13 +62,25 @@ opening path you add MUST follow it: process; if Fusion is ALREADY running, `fusion_start` returns early and the guard never fires, so an already-foreground Fusion stays put. When you need a clean background state, `fusion_kill` first, confirm the process is gone, THEN launch.-- **Seat conflict ("Active Sessions Exceeded") = AUTO-RECLAIM, never ask.** John (2026-07-06): "just- grab the license back… the user can always grab it back on the other machine, so there's no harm."- The dialog is a CEF modal that ignores background `SendInput`, so do NOT try to click it. Instead- `_handle_launch` frees the seat at the SOURCE — `_reclaim_seat_from_peers()` stops Fusion on peer ADs- via the cross-AD direct API (fully background, reliable) — then kills the local instance stuck on the- dialog and relaunches clean (guarded by a one-shot `_seatReclaimAttempted` arg). Do not reintroduce a- notify+ask path for the seat dialog.+- **Seat conflict ("Active Sessions Exceeded") = AUTO-RESOLVE via UIA, in the background, never ask+ (SOLVED live 2026-07-06 after a very long day).** The definitive facts, hard-won:+ - It is a **Qt** dialog (`automationId` = `QTApplication.QTSessionBlockedStartup...`), NOT CEF.+ - Its window **TITLE is literally "Fusion360"** — the "Active Sessions Exceeded" text is body+ content — so detect it by **owning process + dialog size** (`find_licensing_dialog()`), never title.+ - Its native **"Continue"** button IS exposed to **UIA** (`desktop_ui_click {hwnd, name:"Continue"}`),+ and UIA **Invoke runs in the BACKGROUND — no foreground, no focus steal, no cursor move**. Suspend+ is the pre-selected radio, so Continue grabs the license. (The radios themselves are web content+ NOT in the a11y tree — do NOT depend on selecting them.)+ - **DO NOT** kill+relaunch to "free the seat at the source": the Autodesk licensing SERVER keeps the+ seat even when the other machine is OFF, so that never clears it. `_reclaim_seat_from_peers()` is+ dead code, kept only as a comment-marker — do not resurrect it.+ - **DO NOT** coordinate-click it (`desktop_click`/SendInput): that needs foreground (disturbs the+ user) AND the focus-guard fights you by minimizing the dialog.+ - **RETRY + VERIFY.** The FIRST UIA Invoke on a mid-render dialog silently NO-OPs. So the launch loop+ re-invokes "Continue" EVERY tick until `find_licensing_dialog()` no longer sees it — never click+ once and trust it. And a STALE add-in port (port 8774 from a just-killed instance) answers while+ the CURRENT Fusion is blocked behind the dialog, so the seat check must take PRIORITY over the+ add-in probe in both the launch loop and `fusion_readiness` (else you falsely read `ready`). - **The add-in still loads while minimized** — background operation (open/model/export) needs no visible window. So minimized costs you nothing. - **Foreground is opt-in, only to SHOW the user something.** The ONLY time you may foreground/restore