← Commit history

name the EXACT browser profile in the signin stage (profiles are dicts, my filter matched none and fell back to 'your browser'); return signinProfileChoices + forbid vague phrasing in the hints

John Lauer ·6afeb3ec99 ·2mo ago ·parent 48a32e8
6 files changed +72−15
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.6.87+1.6.88
adom-bridge-fusion-manifest.json+5−5
@@ -1,13 +1,13 @@ {   "manifest_version": 1,   "name": "fusion360",-  "version": "1.6.87",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.87/adom-bridge-fusion-v1.6.87.zip",-  "sha256": "9db224ca217b64d811f7b8d08be7357e35ff0ba2cad989a9ea9fbd29fd4610ed",-  "size": 469400,+  "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,   "verbPrefixes": [     "fusion_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-07-20T11:29:10Z"+  "released_at": "2026-07-20T11:35:43Z" }\ 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.87",+  "version": "1.6.88",   "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+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-desktop-fusion-bridge",-  "version": "1.6.87",+  "version": "1.6.88",   "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": {
server.py+55−6
@@ -3578,6 +3578,28 @@ def _orchestrate_fetch_optimized_glb(args: dict) -> dict:             "message": "Job %s still %s; re-call fusion_fetch_optimized_glb to finish." % (job_id, res.get("status") or "processing")}  +def _describe_profile(p: dict) -> str:+    """Human, UNAMBIGUOUS name for a browser profile - never just 'your browser'.++    A power user has several (personal / work / media), so a demo that says "it's in your+    Chrome" is useless (John, 2026-07-20). Produce e.g.+    "Chrome - John Personal ([email protected])" or "Edge - Default"."""+    browser = (p.get("browser") or "browser").strip()+    browser = {"chrome": "Chrome", "edge": "Edge", "brave": "Brave"}.get(browser.lower(), browser.title())+    name = (p.get("displayName") or "").strip()+    email = (p.get("email") or "").strip()+    bits = browser+    if name and email and name.lower() not in email.lower():+        bits += " - %s (%s)" % (name, email)+    elif email:+        bits += " - %s" % email+    elif name:+        bits += " - %s" % name+    elif p.get("profileDir"):+        bits += " - %s" % p.get("profileDir")+    return bits++ def _ad_call(verb: str, args: dict, timeout: int = 60) -> dict:     """Call another AD verb (nbrowser_*, desktop_*) from inside this bridge. @@ -3693,20 +3715,40 @@ 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, "", ""+        choices = []         if nb_state == "ready":             profs = _ad_call("nbrowser_profiles", {}, timeout=40)             pdata = profs.get("data", profs) if isinstance(profs, dict) else {}-            plist = [p for p in (pdata.get("profiles") or []) if isinstance(p, str) and ":" in p]-            profile_used = plist[0] if plist else ""+            # profiles are DICTS: {profile,label,email,browser,displayName,profileDir,active,live,...}+            for p in (pdata.get("profiles") or []):+                if not isinstance(p, dict):+                    continue+                if p.get("blocked") or p.get("unresolved") or not p.get("profile"):+                    continue+                choices.append({+                    "profile": p.get("profile"), "browser": (p.get("browser") or "").lower(),+                    "email": p.get("email") or "", "displayName": p.get("displayName") or "",+                    "profileDir": p.get("profileDir") or "",+                    "active": bool(p.get("active")), "live": bool(p.get("live")),+                    "asleep": bool(p.get("asleep")),+                    "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))+            if pick:+                profile_used = pick["profile"]+                where = pick["describe"]             oa = {"sessionId": "fusion-signin", "url": "https://accounts.autodesk.com/",                   "background": True, "thread": "fusion-demo", "purpose": "Autodesk sign-in for Fusion"}             if profile_used:                 oa["profile"] = profile_used             r = _ad_call("nbrowser_open_window", oa, timeout=60)             opened = bool((r.get("data", r) if isinstance(r, dict) else {}).get("sessionId") or r.get("ok") or r.get("success"))-            where = (profile_used.split(":", 1)[0].title() if profile_used else "your browser")-            if profile_used and "@" in profile_used:-                where += " (%s)" % profile_used.split(":", 1)[1]+            if not where:+                where = "your browser"         if opened:             steps.append("opened Autodesk sign-in in %s (background)" % (where or "browser"))         else:@@ -3725,6 +3767,13 @@ 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>'}. ") ++             "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])'). "+             "`signinProfileChoices` lists every profile with describe/email/displayName/active - if "+             "there is more than one, say which you used and OFFER TO SWITCH (re-run with a different "+             "profile). If the one you want shows extensionInstalled:false it needs the one-time "+             "extension install in THAT profile. "              "TELL THE USER WHERE IT IS WAITING and OFFER ALL THREE: (a) they finish it themselves "              "whenever they want, (b) you foreground that window for them "              "(nbrowser_switch_window / browser window state), or (c) THEY LET YOU DRIVE IT - ask "@@ -3740,7 +3789,7 @@ 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,-            nbState=nb_state)+            signinProfileChoices=choices, nbState=nb_state)      if not rd.get("ready"):         return _out("waiting",
skills/fusion-demo/SKILL.md+9−1
@@ -52,9 +52,17 @@ interrupted. The response tells you where it landed: | Field | Meaning | |---|---| | `signinOpened` | true if the background tab is up |-| `signinWhere` | human phrasing for WHERE, e.g. "Chrome ([email protected])" - say this out loud |+| `signinWhere` | the EXACT place, e.g. "Chrome - John Personal ([email protected])" - say this verbatim |+| `signinProfileChoices` | every profile (describe/email/displayName/active/live/extensionInstalled) | | `signinProfile` / `signinSession` | the ABE profile + sessionId (`fusion-signin`) to drive it | +**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+one you used and offer to switch to another. If the profile they want shows+`extensionInstalled:false`, it needs the one-time extension install in THAT specific profile+(extensions are per-profile).+ **Always tell the user where it is waiting, then offer all three paths:**  1. **They finish it themselves**, whenever they like - it is sitting there, backgrounded.