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+74@@ -11,6 +11,7 @@ Usage: import json import os+import threading import time as _t2 import sys import traceback@@ -3789,6 +3790,75 @@ def _fusion_window_hwnd(): # tree so page buttons/fields ARE reachable by accessible name. So: ALWAYS try background UIA # first and only fall back to a foreground click for things with no UIA node (Fusion's Sign In # button is a webview with none - that is the one documented exception).+# ── SIGN-IN WINDOW JANITOR (John, 2026-07-22) ────────────────────────────────────────────────+# "if you open a browser window for sign in, you must run a loop on a schedule to know when to+# close it so you never leave the user's desktop messy."+# We open browser windows to complete OAuth. Those windows are OURS and must not be left as+# litter once they have served their purpose. Every window we open is tracked here, and a+# background loop closes it as soon as the sign-in it belongs to is DONE (or it is clearly dead+# or too old). Never touches a window the user opened.+_signin_windows = [] # [{sessionId, profile, kind, openedAt}]+_signin_windows_lock = threading.Lock()+_JANITOR_MAX_AGE = 900 # 15 min: an OAuth window older than this is dead weight either way+++def _track_signin_window(session_id, profile, kind="fusion"):+ if not session_id:+ return+ with _signin_windows_lock:+ _signin_windows.append({"sessionId": session_id, "profile": profile,+ "kind": kind, "openedAt": _t2.time()})+++def _close_tracked_window(w) -> bool:+ """Close one window WE opened. nbrowser_close_window only closes our own sessions."""+ r = _ad_call("nbrowser_close_window",+ {"sessionId": w["sessionId"], "profile": w.get("profile")}, timeout=30)+ return isinstance(r, dict) and not r.get("_adCallError")+++def _signin_goal_met(kind) -> bool:+ """Has the sign-in this window exists for actually completed?"""+ try:+ if kind == "aps":+ return bool(_aps_quick_state().get("signedIn"))+ return bool(_unwrap(_handle_fusion_readiness({}, {})).get("ready"))+ except Exception:+ return False+++def _signin_janitor_loop():+ """Poll until each tracked sign-in window can be closed, then close it."""+ while True:+ try:+ _t2.sleep(20)+ with _signin_windows_lock:+ pending = list(_signin_windows)+ if not pending:+ continue+ done_goals = {}+ for w in pending:+ kind = w.get("kind", "fusion")+ if kind not in done_goals:+ done_goals[kind] = _signin_goal_met(kind)+ aged = (_t2.time() - w["openedAt"]) > _JANITOR_MAX_AGE+ if done_goals[kind] or aged:+ if _close_tracked_window(w):+ print("[Fusion Bridge] janitor: closed %s sign-in window %s (%s)"+ % (kind, w["sessionId"], "signed in" if done_goals[kind] else "expired"))+ with _signin_windows_lock:+ if w in _signin_windows:+ _signin_windows.remove(w)+ except Exception:+ continue+++def _start_signin_janitor():+ t = threading.Thread(target=_signin_janitor_loop, daemon=True, name="signin-janitor")+ t.start()+ return t++ def _announce_foreground(reason: str) -> bool: """ALWAYS tell the user WHY, right before we steal their foreground. @@ -4295,6 +4365,9 @@ def _orchestrate_signin(args: dict) -> dict: r = r2 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]))))+ if opened:+ # hand it to the janitor so it is never left as litter on the user's desktop+ _track_signin_window(sess, target, kind="fusion") # ── 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@@ -5118,6 +5191,7 @@ def main(): pass _prune_bridge_logs()+ _start_signin_janitor() port = DEFAULT_PORT if "--port" in sys.argv: