← Commit history

1.9.140: screenshot auto-pull field fix + signin skill gold

John Lauer ·83ebbb0f0c ·1mo ago ·parent 0e6f91a
7 files changed +160−15
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.9.139\ No newline at end of file+1.9.140\ No newline at end of file
adom-bridge-fusion-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "fusion360",-  "version": "1.9.139",-  "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.139/adom-bridge-fusion-v1.9.139.zip",-  "sha256": "c4802f411504b8b3846bd60ff7906006aead2a32b275e879b100508f384f0c5c",-  "size": 474763,+  "version": "1.9.140",+  "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.140/adom-bridge-fusion-v1.9.140.zip",+  "sha256": "2ec401b93b2bdaa7b101b97143cb4c39c5b63bda586cfb45d2bdf7d3b8bea735",+  "size": 475140,   "verbPrefixes": [     "fusion_"   ],
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.9.139",+  "version": "1.9.140",   "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/fusion-bridge",   "author": "Adom Inc.",
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "fusion-bridge",-  "version": "1.9.159",+  "version": "1.9.160",   "type": "app",   "description": "This package installs the bridge's SKILLS into your container so your AI knows how to drive it; Adom Bridge loads the bridge runtime itself from the release zip.",   "dependencies": {
page.json+10−7
@@ -1,6 +1,6 @@ {   "slug": "fusion-bridge",-  "version": "1.9.159",+  "version": "1.9.160",   "type": "app",   "description": "This package installs the bridge's SKILLS into your container so your AI knows how to drive it; Adom Bridge loads the bridge runtime itself from the release zip.",   "dependencies": {@@ -11,6 +11,10 @@     "uninstall": "./uninstall.sh"   },   "tags": [+    "ab",+    "bridge",+    "fusion",+    "desktop-app",     "fusion360",     "autodesk",     "cad",@@ -70,7 +74,10 @@     "build a basic parts library",     "add a 3d model to a component",     "make a fusion 360 library with 3d",-    "set up the fusion bridge"+    "set up the fusion bridge",+    "fusion dashboard",+    "fusion status page",+    "open the fusion launch page"   ],   "discovery_pitch": "Use the Adom Bridge 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 Bridge. 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 Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.",@@ -99,9 +106,5 @@       "label": "Part volume",       "prompt": "How much material does each printed part in this assembly use?"     }-  ],-  "author": {-    "name": "John Lauer",-    "email": "[email protected]"-  }+  ] }\ No newline at end of file
server.py+20−1
@@ -1281,7 +1281,26 @@ def _handle_screenshot_fusion(fusion_info: dict, args: dict) -> dict:     else:         result = screenshot_fusion_window()     if result.get("success"):-        result["output"] = json.dumps({"savedTo": result["savedTo"], "sizeKB": result["sizeKB"]})+        # This bridge natively names the shot `savedTo`/`sizeKB`/`dimensions`, but AD's CLI+        # auto-pulls a screenshot into the CALLER'S container by keying on the ab-core field+        # names (fullPath/safePath/fullPathHost/safePathHost + fullWidth/fullHeight). Without+        # those, `savedTo` is a Windows-only path the container can't read and the shot looks+        # "null" from the cloud (fusion-bridge#: field-name mismatch, John 2026-08-22). Alias+        # them so the pull fires and callers get localSafePath/localFullPath just like desktop_*.+        _saved = result.get("savedTo")+        if _saved:+            for _k in ("fullPath", "safePath", "fullPathHost", "safePathHost"):+                result.setdefault(_k, _saved)+        _dims = result.get("dimensions") or {}+        if _dims.get("width"):+            result.setdefault("fullWidth", _dims.get("width"))+            result.setdefault("fullHeight", _dims.get("height"))+        result["output"] = json.dumps({+            "savedTo": _saved, "sizeKB": result.get("sizeKB"),+            "fullPath": _saved, "safePath": _saved,+            "fullPathHost": _saved, "safePathHost": _saved,+            "fullWidth": _dims.get("width"), "fullHeight": _dims.get("height"),+        })     return result  
skills/fusion-multiprofile-signin/SKILL.md+123
@@ -100,10 +100,133 @@ Two things bite after the profile fix works:    UIA Invoke no-ops). This step is the same for ALL Fusion sign-ins; it is not caused by the profile    move. +## ⭐ THE PROVEN APPROACH (John's directive, 2026-08-22) - DO NOT over-automate this++After hours of trying to fully automate the desktop sign-in, John's ruling is: **trigger the sign-in,+then put up an AD CAPTION asking the USER to complete it in the browser window that just opened, and+STOP. Do not try to automate the browser-side auth or the protocol handoff.** The exact flow:++1. **If switching accounts:** sign the current user out first (reset the shared Autodesk identity, see+   "Signing OUT" below), then `fusion_stop`/`fusion_start` so Fusion comes up `needsSignin:true`.+2. **Trigger the sign-in with UIA, not screenshots.** The Fusion "Welcome to Fusion" modal exposes a+   **"Sign In" button in the accessibility tree** (`desktop_find_control {hwnd, name:"Sign In"}` returns+   `invokable:true` with a real screen rect, e.g. center ~1279,910). Click it in the BACKGROUND with+   `desktop_ui_click {hwnd, name:"Sign In"}` - no foreground, no capture, no focus steal. (Get the hwnd+   from `Get-Process Fusion360 | MainWindowHandle` - `desktop_list_windows` sometimes misses it.) This+   makes Fusion open the OS-default browser to `signin.autodesk.com/?flowId=...`.+3. **Detect the browser auth window** (you CAN): `Get-Process chrome|msedge | Where MainWindowTitle -match+   "Sign in - Autodesk"` gives its hwnd, and `nbrowser_list_tabs {profile}` shows which profile+tab holds+   the `signin.autodesk.com` flow.+4. **Put an AD caption on that browser window asking the user to finish**, then poll and STOP automating:+   `desktop_caption {hwnd:<auth window>, text:"Please finish signing in as <email> here", subtext:"Adom+   will detect when it completes"}`. Do NOT drive the page, do NOT reopen the flow elsewhere, do NOT click+   the protocol dialog. John completes it by hand.+5. **Remind the user about "Open Product" (the commonly-missed step, John 2026-08-22).** After the web+   sign-in succeeds, the browser lands on a **"You're signed in - Open Product"** page. The user MUST+   click **"Open Product"** (and clear any "Open Autodesk Identity Manager?" native dialog) for the+   `adsk.idmgr://` handoff to reach Fusion. Fusion sits on "Signing in - Autodesk Fusion" indefinitely+   until they do. If the disk/title shows no completion ~30-60s after the web auth, **caption the auth+   window reminding them: "click Open Product to finish"**. This is the single most common reason it+   looks stuck.+6. **Detect completion via DISK** (the add-in is blocked by the modal so `fusion_*` verbs time out):+   a per-user folder appears/updates at `%LOCALAPPDATA%\Autodesk\Autodesk Fusion 360\<AUTODESK_USER_ID>\`+   (john=`X3G293QFLPJERKGZ`), and the window title flips off "Signing in - Autodesk Fusion".+7. **After the handoff, Fusion may show a NEW account/hub-selection screen** (seen first time on a+   personal Google-federated account, 2026-08-22) - this is where the user can pick which **hub** (e.g.+   their **personal hub**) to connect to. Not an error; capture it, show it in shotlog, and let the user+   choose. This is a great real-world test of a fresh personal-account sign-in.++### Why we do NOT automate the browser side (all tried and failed, 2026-08-22)+- Fusion opens the **OS-default browser profile** (john's `Default`), NOT the target account's profile.+  The `signin.autodesk.com/?flowId=...` flow is **locked to that browser session** - reopening the same+  flowId in another profile returns **"Unable to access this link"**, so you cannot redirect it.+- `nbrowser_*` **refuses to drive the user's own (unowned) window**, so you cannot fill that tab.+- The final `adsk.idmgr://` protocol handoff pops a **native Chrome dialog** that no screenshot can see+  and UIA exposes only intermittently. Even with the `AutoLaunchProtocolsFromOrigins` policy set (below),+  completion was unreliable. Automating past this point wastes the user's time - caption and hand off.++### Screenshot facts learned the hard way (2026-08-22)+- **`desktop_screenshot_window {hwnd}` works on a BACKGROUND window** (no foreground needed) - but the+  window must NOT be minimized (a minimized window has no surface; un-minimize with `ShowWindow(hwnd,4)`+  = SW_SHOWNOACTIVATE to bring it back to the background without stealing focus).+- **NEVER take fullscreen screenshots** (John's rule) - always `desktop_screenshot_window`.+- **The "screenshots return null" scare was a FIELD-NAME/parse bug, not a broken capture.** `desktop_+  screenshot_*` returns the image path at **top-level `localSafePath`** (and `localFullPath`), and+  ab-core auto-pulls the PNG into the container. Do NOT descend into the response's `output` sub-object+  (that holds `{data:{image:base64...}}` and has NO `localSafePath`) - reading `localSafePath` off+  `output` yields null and looks like a failed shot. The Fusion bridge's OWN `fusion_screenshot_fusion`+  uses DIFFERENT keys (`savedTo`, `dimensions.{width,height}`, `sizeKB`) and does NOT auto-pull, so a+  caller keying on `fullPathHost`/`localSafePath` gets null there too - read `savedTo`.+- Capture can transiently return null under **contention** with another thread capturing heavily - retry.+- Always show your work: `adom-shotlog inject -c <ch> -d "..." <path>` so the user sees exactly what you+  captured, and caption each foreground step ("taking window screenshot" / "done - back to background")+  so the user knows when they can alt-tab away.++## PERMANENT FIX for the protocol dialog (John, 2026-08-22) - set it BEFORE sign-in++The `autodesk://`/`adskidmgr://` "Open Autodesk Identity Manager?" dialog is the #1 blocker and it is+a NATIVE OS dialog (not DOM, not always in the UIA tree). Kill it forever with Chrome/Edge policy so+the protocol auto-launches with NO dialog, for every profile and every future user. Set it in HKCU+(no admin) BEFORE driving the sign-in, then RESTART the browser so it loads the policy:++```+# HKCU\SOFTWARE\Policies\Google\Chrome\AutoLaunchProtocolsFromOrigins   (and ...\Microsoft\Edge\...)+#   value "1" = {"protocol":"adskidmgr","allowed_origins":["*"]}+#   value "2" = {"protocol":"autodesk","allowed_origins":["*"]}+# then: taskkill chrome (NOT Chrome-for-Testing), relaunch with --restore-last-session+```++Chrome only reads this policy at startup, so a running Chrome must be restarted (tabs restore). This is+the single change that makes desktop sign-in hands-free. **This should be baked into `fusion_signin`+itself** so the bridge sets the policy automatically before every sign-in - build it into the verb, do+not rely on the AI remembering to do it.++## ⛔ THE HARD WALL: Fusion's sign-in modal is a GPU-protected, UNCAPTURABLE surface (2026-08-22)++Learned the very hard way over hours. When Fusion sits on **"Signing in - Autodesk Fusion"** waiting+for the browser, that modal blocks EVERY visual-automation technique:++- **Screen/window capture returns NULL** for it - `desktop_screenshot_window {hwnd}` AND+  `desktop_screenshot_screen` (once Fusion is foregrounded) both come back with no image (WGC/BitBlt/+  PrintWindow all fail on Fusion's hardware-accelerated overlay). So screenshot-then-click-by-coord is+  IMPOSSIBLE on this modal - do not burn time trying to capture it.+- **`desktop_list_windows` returns 0 windows** while this modal is up (enumeration wedges). Get the+  Fusion hwnd via PowerShell `Get-Process Fusion360 | MainWindowHandle` instead.+- **The modal blocks Fusion's ADD-IN** (main-thread), so `fusion_readiness`/`fusion_signin` and all+  `fusion_*` verbs TIME OUT. The bridge CORE verbs (`run_script`, `desktop_*`, `nbrowser_*`) still work.+  Check sign-in progress via DISK instead: a per-user folder appears at+  `%LOCALAPPDATA%\Autodesk\Autodesk Fusion 360\<AUTODESK_USER_ID>\` (e.g. jlauer12 = `LMFMLDP33E65`,+  john = `X3G293QFLPJERKGZ`).+- **Fusion launches foreground-LOCKED**, so a bare `SetForegroundWindow` is ignored and your SendInput+  clicks land nowhere. Defeat it with the ALT-key + AttachThreadInput trick (press ALT, attach to the+  current foreground thread, then SetForegroundWindow) - verified to make `GetForegroundWindow()==hwnd`.+- Even then, blind SendInput clicks and keyboard (Enter/Tab/Space) did NOT activate the modal's+  "Retry browser sign-in" button in a degraded-capture state.++**CONCLUSION / the way that actually works:** do NOT try to click this modal. Instead make the flow+never need a click: (1) set the AutoLaunchProtocols policy above, (2) pre-sign the target profile into+Autodesk (warm session) so OAuth auto-consents, (3) let Fusion open the browser (it does so on its own+when it enters sign-in, OR one human click of "Retry browser sign-in" that then completes fully+hands-free because of the policy). **Switching a personal Google-federated account onto the Fusion+DESKTOP app, on a machine whose desktop-capture subsystem is degraded, may still need ONE human click+on that modal - that is a genuine capability limit, not a skipped step. Say so honestly and stop; do+not flail.** To un-break a machine left signed-out, restore the backed-up+`Identity Services\idservices.db` + the user folder.++## Signing OUT to switch accounts (no fusion_signout verb exists)++Fusion caches the login in the SHARED `%LOCALAPPDATA%\Autodesk\Identity Services\idservices.db` (used by+ALL Autodesk desktop apps). To force a clean signed-out state: BACK IT UP first, then `fusion_stop`,+stop `IdentityService`/`IdentityUpdateService`, move `idservices.db` aside, `fusion_start` -> Fusion+comes up `needsSignin:true`. Restore = reverse it. `fusion_signin` takes a **`profile`** param+(`chrome:<email>`) to open the OAuth in a specific profile.+ ## Gotchas  - Read History AFTER Fusion has opened the browser, and take the NEWEST authorize entry - a stale one   from a previous attempt carries a dead `request_id` and Fusion (waiting on a new one) never gets it.+- Do NOT close the Autodesk callback tabs Fusion opens - closing them removes Fusion's pending browser+  handoff and forces you back to the un-clickable "Retry" modal. - If the wrong account completes in the default browser before you move it, sign Fusion out and re-run. - Chrome keeps History locked; always COPY the file before opening it (the verb does this). - This is also the sign-in stage `fusion_demo` uses, so a first-time demo never lands in the wrong