← Commit history

profile selection by EVIDENCE: probe every live profile with nbrowser_login_state against accounts.autodesk.com and pick the one holding a real Autodesk session; report the reason + flag ambiguity instead of guessing 'active'

John Lauer ·30202b1e12 ·2mo ago ·parent b68545d
6 files changed +81−19
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.6.88+1.6.89
adom-bridge-fusion-manifest.json+5−5
@@ -1,13 +1,13 @@ {   "manifest_version": 1,   "name": "fusion360",-  "version": "1.6.88",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.88/adom-bridge-fusion-v1.6.88.zip",-  "sha256": "1561b38456bdbaac98e91936a0e02f6e9adc8d6d48f9185887b6e67c0eae2ef1",-  "size": 470464,+  "version": "1.6.89",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.89/adom-bridge-fusion-v1.6.89.zip",+  "sha256": "fa347850bbf515ab7497cc594133b5824c696b1b60caa82da725e03516738311",+  "size": 471956,   "verbPrefixes": [     "fusion_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-07-20T11:35:43Z"+  "released_at": "2026-07-20T11:37:59Z" }\ No newline at end of file
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.6.88",+  "version": "1.6.89",   "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.",
page.json+2−3
@@ -1,6 +1,6 @@ {   "slug": "adom-desktop-fusion-bridge",-  "version": "1.6.88",+  "version": "1.6.89",   "type": "app",   "description": "Installs this bridge's skills into your container so your AI knows how to drive the bridge. The bridge runtime itself is loaded by Adom Desktop from the release zip.",   "dependencies": {@@ -73,6 +73,5 @@     "set up the fusion bridge"   ],   "discovery_pitch": "Use the Adom Desktop Fusion 360 bridge when the user wants to DRIVE Autodesk Fusion 360 from the cloud: open/search their team's Fusion cloud designs, lay out a PCB or do electronics, export STEP/IGES/STL/Gerbers/BOM, or build a component library with real rendering 3D. It runs Fusion on the user's own machine via Adom Desktop. NOT for web/browser/login/form-filling (that's the native-browser extension) and NOT for KiCad (that's the kicad bridge).",-  "brief": "Drive Autodesk Fusion 360 from the cloud via Adom Desktop: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.",-  "visibility": "public"+  "brief": "Drive Autodesk Fusion 360 from the cloud via Adom Desktop: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling." }\ No newline at end of file
server.py+54−9
@@ -3715,6 +3715,7 @@ def _orchestrate_demo(args: dict) -> dict:         nb_data = nb.get("data", nb) if isinstance(nb, dict) else {}         nb_state = nb_data.get("state")         opened, where, profile_used = False, "", ""+        pick_reason, ambiguous = "", False         choices = []         if nb_state == "ready":             profs = _ad_call("nbrowser_profiles", {}, timeout=40)@@ -3734,10 +3735,46 @@ def _orchestrate_demo(args: dict) -> dict:                     "extensionInstalled": p.get("extensionInstalled", True),                     "describe": _describe_profile(p),                 })-            # prefer: currently ACTIVE + live, then any live, then anything-            pick = (next((c for c in choices if c["active"] and c["live"]), None)-                    or next((c for c in choices if c["live"]), None)-                    or (choices[0] if choices else None))+            # PROBE each profile for a REAL Autodesk session - never guess by "active".+            # (John, 2026-07-20: picking the active profile grabbed his PERSONAL Chrome with+            # zero analysis. A power user's Autodesk login can live in any profile, so ASK THE+            # BROWSER, don't assume.) nbrowser_login_state reports auth cookies per profile.+            for c in choices:+                if not c["live"]:+                    c["autodesk"] = "unprobed(asleep)"+                    continue+                ls = _ad_call("nbrowser_login_state",+                              {"profile": c["profile"], "url": "https://accounts.autodesk.com/"},+                              timeout=45)+                lsd = ls.get("data", ls) if isinstance(ls, dict) else {}+                if lsd.get("ok") is None and lsd.get("loggedIn") is None:+                    c["autodesk"] = "unprobed"+                else:+                    c["autodesk"] = "signed-in" if lsd.get("loggedIn") else "signed-out"+                c["autodeskConfidence"] = lsd.get("confidence")+                c["autodeskCookies"] = lsd.get("cookieCount")+            _CONF = {"high": 3, "medium": 2, "low": 1}+            signed = [c for c in choices if c.get("autodesk") == "signed-in"]+            signed.sort(key=lambda c: (_CONF.get(c.get("autodeskConfidence"), 0),+                                       c.get("autodeskCookies") or 0), reverse=True)+            pick = signed[0] if signed else None+            if pick:+                pick_reason = ("it is the profile actually signed into Autodesk (%s auth cookies, %s "+                               "confidence)" % (pick.get("autodeskCookies"), pick.get("autodeskConfidence")))+            else:+                # NOTHING is signed in - do not silently guess. Prefer a work/corporate identity+                # over a consumer mailbox (Autodesk seats are usually work accounts), but SAY SO+                # and offer the alternatives.+                _CONSUMER = ("gmail.com", "outlook.com", "hotmail.com", "yahoo.com", "icloud.com", "live.com")+                def _work_first(c):+                    em = (c.get("email") or "").lower()+                    return (0 if (em and not any(em.endswith("@" + d) for d in _CONSUMER)) else 1,+                            0 if c["live"] else 1)+                ranked = sorted([c for c in choices if c["live"]] or choices, key=_work_first)+                pick = ranked[0] if ranked else None+                pick_reason = ("no profile has a live Autodesk session, so I picked the most likely "+                               "one (work/corporate identity first) - CONFIRM WITH THE USER")+            ambiguous = not signed or len(signed) > 1             if pick:                 profile_used = pick["profile"]                 where = pick["describe"]@@ -3754,10 +3791,11 @@ def _orchestrate_demo(args: dict) -> dict:         else:             steps.append("could not auto-open the browser sign-in: %s" % (nb.get("_adCallError") or nb_state or "unknown"))         if opened:-            narrate = ("I've opened the Autodesk sign-in for you in %s - it's sitting in the "-                       "background so it won't interrupt what you're doing. Finish it whenever you "-                       "like, or say the word and I'll bring it up front, or I can just complete it "-                       "for you." % where)+            narrate = ("I've opened the Autodesk sign-in in %s - I chose that profile because %s. "+                       "It's sitting in the background so it won't interrupt what you're doing. "+                       "Finish it whenever you like, tell me to bring it up front, or I can complete "+                       "it for you. If that's the wrong account, say which profile to use."+                       % (where, pick_reason))         else:             narrate = ("Fusion needs your Autodesk sign-in. I'd like to use your own browser - you're "                        "probably already signed in there, so it should take one click.")@@ -3767,6 +3805,12 @@ def _orchestrate_demo(args: dict) -> dict:               if opened else "Auto-open failed - open it yourself: nbrowser_open_window "               "{sessionId:'fusion-signin', url:'https://accounts.autodesk.com/', background:true, "               "profile:'<chrome:their-account>'}. ") ++             "The profile was CHOSEN BY EVIDENCE, not guessed: each live profile was probed with "+             "nbrowser_login_state against accounts.autodesk.com, and the one holding a real Autodesk "+             "session wins (see signinProfileReason + per-profile autodesk/autodeskConfidence/"+             "autodeskCookies in signinProfileChoices). RELAY THAT REASON to the user. If "+             "signinProfileAmbiguous is true (nothing signed in, or several are), ASK them which "+             "account their Autodesk login belongs to instead of assuming. "              "NAME THE EXACT PROFILE - never say just 'your browser' or 'your Chrome'. Power users "              "run several profiles (personal / work / media), so say the browser AND the identity "              "from `signinWhere` (e.g. 'Chrome - John Personal ([email protected])'). "@@ -3789,7 +3833,8 @@ def _orchestrate_demo(args: dict) -> dict:              "fusion-autodesk-signin."),             needsSignin=True, signinOpened=opened, signinWhere=where,             signinProfile=profile_used, signinSession="fusion-signin" if opened else None,-            signinProfileChoices=choices, nbState=nb_state)+            signinProfileChoices=choices, signinProfileReason=pick_reason,+            signinProfileAmbiguous=ambiguous, nbState=nb_state)      if not rd.get("ready"):         return _out("waiting",
skills/fusion-demo/SKILL.md+18
@@ -56,6 +56,24 @@ interrupted. The response tells you where it landed: | `signinProfileChoices` | every profile (describe/email/displayName/active/live/extensionInstalled) | | `signinProfile` / `signinSession` | the ABE profile + sessionId (`fusion-signin`) to drive it | +### Pick the profile by EVIDENCE, never by "whichever is active"++`fusion_demo` probes **every live profile** with+`nbrowser_login_state {profile, url:"https://accounts.autodesk.com/"}` and picks the one that+actually holds an Autodesk session (auth cookies), reporting why in `signinProfileReason` and the+per-profile `autodesk` / `autodeskConfidence` / `autodeskCookies` in `signinProfileChoices`.++This exists because the first version just grabbed the *active* profile and landed in John's+**personal** Chrome with no analysis at all - on another machine that would have been simply wrong.+A user's Autodesk seat can live in any profile, and it is frequently NOT the one they happen to be+using. **Ask the browser; do not assume.**++- **Relay the reason** to the user ("I used X because it's the profile actually signed into Autodesk").+- If `signinProfileAmbiguous` is true (nothing signed in anywhere, or several are), **ASK which+  account their Autodesk login belongs to** rather than picking for them.+- Profiles that are asleep or lack the extension come back `unprobed` - say so instead of silently+  skipping them.+ **Never say "it's in your browser" or even "your Chrome".** A power user runs several profiles - personal, work, media - and a vague pointer sends them hunting through windows. Always name the browser AND the identity from `signinWhere`. If `signinProfileChoices` has more than one, say which