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
server.py+182−1@@ -11,6 +11,7 @@ Usage: import json import os+import time as _t2 import sys import traceback import urllib.request@@ -1193,6 +1194,17 @@ def _handle_install_fusion(fusion_info: dict, args: dict) -> dict: } +def _aps_quick_state() -> dict:+ """Cheap APS state for readiness: {configured, signedIn}. Never raises, never blocks."""+ try:+ import aps as _aps+ st = _aps.handle_status({}) or {}+ d = st.get("data", st)+ return {"configured": bool(d.get("configured")), "signedIn": bool(d.get("signedIn"))}+ except Exception:+ return {"configured": None, "signedIn": None}++ def _handle_fusion_readiness(fusion_info: dict, args: dict) -> dict: """FAST readiness check for the AI: is the Fusion host app present + running + the bridge ready? Does NOT launch Fusion (fast-fails when it's not running). AD DETECTS Fusion (never installs it)@@ -1354,7 +1366,25 @@ def _handle_fusion_readiness(fusion_info: dict, args: dict) -> dict: elif ready and stale_info.get("addinStale"): hint = stale_info["_staleHint"] elif ready:- hint = "READY - drive Fusion (fusion_open_lbr / build_library_3d / etc.)."+ # APS is checked on EVERY launch now (John, 2026-07-22: "why aren't those just driven from+ # 1 login?"). Fusion sign-in and APS are both Autodesk logins; the user should authenticate+ # ONCE. They cannot share a token (Autodesk DPAPI-encrypts Fusion's store), but they CAN+ # share the warm browser SSO session - so APS consent is silent right after a Fusion login.+ _aps = _aps_quick_state()+ if _aps.get("signedIn"):+ hint = ("READY - drive Fusion (fusion_open_lbr / build_library_3d / etc.). APS cloud "+ "search is signed in too, so use fusion_aps_search for ~2s cloud lookups.")+ elif _aps.get("configured"):+ hint = ("READY to drive Fusion, but APS CLOUD SEARCH IS NOT SIGNED IN - cloud file "+ "search will be slow/blocked. DO IT NOW, do not make the user log in a second "+ "time: call fusion_aps_signin RIGHT AFTER a Fusion sign-in, while the browser "+ "profile still has a warm Autodesk SSO session - it consents silently (no "+ "password, no 2FA). Then fusion_aps_search works.")+ else:+ hint = ("READY to drive Fusion. APS cloud search is NOT SET UP (no client ID) - cloud "+ "search is the slow path without it. Offer to set it up: fusion_aps_set_client_id "+ "then fusion_aps_signin (silent while the browser SSO session is warm). APS is "+ "how cloud search gets to ~2 seconds.") elif installed and running and licensing: hint = ("Fusion is blocked by a SEAT/LICENSING dialog ('Active Sessions Exceeded' / 'Suspend " "Remote Session') - detected DETERMINISTICALLY as an OWNED POPUP of the main Fusion "@@ -3949,6 +3979,61 @@ def _capture_fresh_authorize(wait_sec: int = 30, max_age: int = 120): _t.sleep(2) +_SSO_BUTTONS = {"google": "Continue with Google", "apple": "Continue with Apple",+ "microsoft": "Continue with Microsoft", "facebook": "Continue with Facebook"}+++def _drive_sso_signin(profile: str, tab_id, email: str, provider: str = "google") -> dict:+ """Finish the Autodesk sign-in over CDP using SSO - NO password, NO 2FA, NO foreground.++ PROVEN LIVE (John, 2026-07-22) after password/2FA attempts kept stalling. If the browser+ PROFILE is already signed into the identity provider (a work Google account is the common+ case), "Continue with Google" -> pick the account -> "Open Product" completes the whole login+ silently and hands the token back to Fusion via the autodesk:// callback.++ TWO THINGS MATTER:+ 1. It must be a FRESH flow. Resuming a flowId that already advanced past the provider+ choice lands you on the PASSWORD screen with no way back - that dead end cost us an hour.+ 2. Click the provider BEFORE typing any email; entering an email commits to the password path.+ """+ steps = []++ def ev(expr):+ r = _unwrap(_ad_call("nbrowser_eval", {"profile": profile, "tabId": tab_id,+ "expression": expr}, timeout=45))+ return r.get("result") or r.get("value")++ def click(text=None, selector=None):+ a = {"profile": profile, "tabId": tab_id}+ if text: a["text"] = text+ if selector: a["selector"] = selector+ r = _unwrap(_ad_call("nbrowser_click", a, timeout=45))+ return bool(r.get("ok") or r.get("success") or r.get("changed"))++ btn = _SSO_BUTTONS.get((provider or "google").lower(), _SSO_BUTTONS["google"])+ if not click(text=btn):+ return {"done": False, "steps": steps,+ "why": "%r not on the page - this is probably NOT a fresh flow (a resumed flowId "+ "goes straight to the password screen)." % btn}+ steps.append("clicked %r" % btn)+ _t2.sleep(7)++ # provider account chooser - pick by the exact email+ if email and click(text=email):+ steps.append("picked the %s account" % email)+ _t2.sleep(8)++ state = str(ev("JSON.stringify({u:location.href.slice(0,120),b:document.body.innerText.slice(0,200)})") or "")+ if "You're signed in" in state or "signed in" in state.lower():+ steps.append("provider returned 'You're signed in'")+ # hand the token back to Fusion (autodesk:// protocol callback)+ if click(text="Open Product"):+ steps.append("clicked 'Open Product' to hand the token to Fusion")+ return {"done": True, "steps": steps, "state": state[:200]}+ return {"done": False, "steps": steps, "state": state[:200],+ "why": "did not reach the signed-in page; a provider password/2FA may be required"}++ def _orchestrate_signin_2fa(args: dict) -> dict: """Submit Autodesk's emailed 6-digit verification code, IN THE BACKGROUND. @@ -4150,6 +4235,41 @@ def _orchestrate_signin(args: dict) -> dict: tdesc = next((_describe_profile(c) for c in choices if c.get("profile") == target), target) import time as _tt sess = "fusion-signin-%d" % int(_tt.time()) # unique per attempt (a reused id can be refused)+ # ── Is Fusion ALREADY using the right profile? (John, 2026-07-22: "they both opened in my+ # work profile, so you're being lazy") ──────────────────────────────────────────────────+ # Chrome profile DIRECTORIES are named Default / Profile 1 / Profile 2, and the user's work+ # account is very often just "Default". We capture the authorize URL from a profile DIR, but+ # the target is an EMAIL (chrome:[email protected]). Without mapping email -> dir we cannot tell+ # they are the SAME profile, so we "fixed" a non-problem by re-opening the identical URL in+ # the identical profile - a redundant second sign-in window on the user's screen.+ target_dir = None+ for c in choices:+ if c.get("profile") == target:+ target_dir = c.get("profileDir") or c.get("dir")+ break+ if target_dir and auth.get("sourceProfileDir") and \+ str(target_dir).strip().lower() == str(auth["sourceProfileDir"]).strip().lower():+ steps.append("Fusion already opened the sign-in in %s (profile dir %r) - no re-open needed"+ % (target, target_dir))+ wall0 = _detect_signin_wall()+ notified0 = bool(_notify_signin_wall(wall0["wall"]).get("delivered")) if wall0.get("wall") else False+ return {"success": True, "stage": "already_right_profile", "done": False, "steps": steps,+ "signinProfile": target, "signinProfileDir": target_dir,+ "signinWhere": tdesc if False else target,+ "signinWall": wall0.get("wall"), "signinWallHwnd": wall0.get("hwnd"),+ "notifyDelivered": notified0,+ "signinWallHint": _wall_hint(wall0["wall"], notified0) if wall0.get("wall") else None,+ "signinAuthUrl": auth["url"],+ "narrate": ("Fusion opened its sign-in in the RIGHT profile already (%s), so I did "+ "not open a second window." % target),+ "_hint": ("NO re-open was needed - Fusion's OS-default browser IS the user's Autodesk "+ "profile here (dir %r). Do NOT open another window; that just litters their "+ "screen with a duplicate sign-in. The existing window is the one to finish. "+ "%s" % (target_dir,+ _wall_hint(wall0["wall"], notified0) if wall0.get("wall")+ else "Poll fusion_readiness until ready:true.")),+ "statusVerb": "fusion_readiness"}+ # snapshot the Autodesk windows that already exist, so a STALE expired tab from an earlier # attempt is never mistaken for this attempt's wall pre_hwnds = _autodesk_window_hwnds()@@ -4176,6 +4296,67 @@ def _orchestrate_signin(args: dict) -> dict: steps.append((("re-opened it in %s%s" % (tdesc, " (extension-free)" if open_via == "extension_free" else "")) if opened else ("could not open %s (raw: %s)" % (tdesc, str(r)[:160])))) + # ── FINISH IT: drive the SSO path ourselves (no password, no 2FA, no foreground) ──────────+ # John, 2026-07-22: the goal is a SIGNED-IN Fusion, not a handed-off checklist. When we own+ # the window (nbrowser_open_window => agent-opened => CDP-drivable) and the profile is already+ # signed into the identity provider, this completes the whole login silently.+ sso = None+ if opened and open_via == "extension" and args.get("driveSso", True):+ tabs = _unwrap(_ad_call("nbrowser_list_tabs", {"profile": target}, timeout=45)).get("tabs") or []+ my_tab = None+ for t in tabs:+ if "autodesk" in str(t.get("url", "")).lower() and t.get("owner") == "agent-opened":+ my_tab = t.get("tabId") or t.get("id")+ if my_tab:+ email = None+ for c in choices:+ if c.get("profile") == target:+ email = c.get("email")+ sso = _drive_sso_signin(target, my_tab, email, args.get("ssoProvider", "google"))+ steps.extend(sso.get("steps") or [])+ if sso.get("done"):+ for _ in range(6):+ _t2.sleep(5)+ if _unwrap(_handle_fusion_readiness({}, {})).get("ready"):+ steps.append("Fusion reports ready:true - SIGNED IN")+ # ── ONE LOGIN, BOTH SYSTEMS (John, 2026-07-22) ───────────────────────+ # "why should the user have to login twice to autodesk to sign in to+ # fusion and setup aps? why aren't those just driven from 1 login?"+ # Right now the browser profile has a WARM Autodesk SSO session (we just+ # used it). APS consent rides that session silently, so do it HERE while+ # it is warm instead of making the user authenticate a second time.+ aps_state = _aps_quick_state()+ if aps_state.get("configured") and not aps_state.get("signedIn"):+ try:+ import aps as _apsmod+ _apsmod.start_signin({"profile": target})+ steps.append("APS not signed in - started its consent on the SAME "+ "warm SSO session (no second login for the user)")+ for _ in range(5):+ _t2.sleep(4)+ if _aps_quick_state().get("signedIn"):+ steps.append("APS signed in too - one login covered both")+ break+ except Exception as e:+ steps.append("APS auto-setup skipped (%s)" % str(e)[:80])+ aps_state = _aps_quick_state()+ return {"success": True, "stage": "signed_in", "done": True, "steps": steps,+ "signinProfile": target, "signinWhere": tdesc,+ "signinOpenedVia": open_via,+ "aps": aps_state,+ "narrate": ("Fusion is signed in as %s. No password or 2FA was needed - "+ "I used the browser profile's existing SSO session.%s"+ % (email or target,+ " APS cloud search is set up too, from the same login."+ if aps_state.get("signedIn") else "")),+ "_hint": ("DONE - Fusion is signed in (ready:true). Nothing else to do; "+ "do not tell the user to sign in. %s Drive Fusion normally now."+ % ("APS is signed in as well, so fusion_aps_search is live."+ if aps_state.get("signedIn") else+ "APS is NOT signed in - run fusion_aps_signin NOW while the "+ "browser SSO session is still warm so it consents silently.")),+ "statusVerb": "fusion_readiness"}+ # Did the reopened sign-in immediately hit a HUMAN WALL (2FA, credentials, protocol dialog)? # If so, toast the user AND tell the AI how to clear it for them. wall = _detect_signin_wall(ignore_hwnds=pre_hwnds) if opened else {}