← Commit history

v1.6.67: notify reach_user uses target=all (peers() broke on 'targets'->'clients' shape drift, so a VM toast hit only itself); recognize broadcast summary as success + report reached desktops; peers() tolerant of clients shape

John Lauer ·3bfdeb08ff ·3mo ago ·parent bbc3761
5 files changed +30−21
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.6.66\ No newline at end of file+1.6.67\ No newline at end of file
ad_client.py+10−3
@@ -239,13 +239,16 @@ def self_name(): def peers():     """clientNames of the OTHER ADs on the relay (excludes self). [] if none/unknown."""     res = call("targets") or {}-    tlist = res.get("targets") if isinstance(res, dict) else None+    # tolerate shape drift: the peer list is under `clients` on current AD, `targets` on older.+    tlist = None+    if isinstance(res, dict):+        tlist = res.get("targets") or res.get("clients")     if not isinstance(tlist, list):         return []     me = self_name()     out = []     for t in tlist:-        n = (t or {}).get("name") or (t or {}).get("hostname")+        n = t if isinstance(t, str) else ((t or {}).get("name") or (t or {}).get("hostname") or (t or {}).get("clientName"))         if n and n != me:             out.append(n)     return out@@ -267,7 +270,11 @@ def notify(title, body, level="info", buttons=None, target=None, reach_user=Fals     if buttons:         args["buttons"] = buttons     tgt = target-    if tgt is None and reach_user and peers():+    if tgt is None and reach_user:+        # Fan out to EVERY connected desktop so the toast lands wherever the user actually is. Do NOT+        # gate on peers() (John 2026-07-14): the `targets` response shape drifted to {clients:[...]}+        # so peers() wrongly returns [] and the toast would hit only THIS (unattended VM). The relay+        # honors target="all" directly - verified reaching the user's laptop.         tgt = "all"     res = call("notify_user", args, target=tgt)     return res
adom-bridge-fusion-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "fusion360",-  "version": "1.6.66",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.66/adom-bridge-fusion-v1.6.66.zip",-  "sha256": "64833c2f7d513837e4a70b86f2de3939c57c7dee06b5ad46f2a326c03869e479",-  "size": 360022,+  "version": "1.6.67",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-fusion-bridge/1.6.67/adom-bridge-fusion-v1.6.67.zip",+  "sha256": "1d5c3a7ff010fd90b8ad995c51fc2fa930140890b12be6624dfe56246ed80c14",+  "size": 360402,   "verbPrefixes": [     "fusion_"   ],
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.6.66",+  "version": "1.6.67",   "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.",
server.py+14−12
@@ -282,20 +282,22 @@ def _handle_notify_owner(args: dict) -> dict:             "_hint": ("Relay the notifyUser payload yourself: `adom-desktop --target all notify_user "                       "{title, body, level}` (or `--target <the user's host>`)."),         }-    peers = []-    try:-        peers = ad_client.peers()-    except Exception:-        pass-    res = ad_client.notify(title, body, level=level, reach_user=True)-    ok = bool(res and (res.get("success") or res.get("status") == "ok"))+    res = ad_client.notify(title, body, level=level, reach_user=True) or {}+    # reach_user fans out via target="all", whose response is a BROADCAST envelope+    # {results:{host:{action}}, summary:{ok,failed,total}, targets:[...]}. Recognize that shape for+    # success (summary.ok>0) - not just the single-target {status:"ok"} - and report the ACTUAL+    # desktops reached, so a toast that landed on the user's laptop isn't mis-reported as failed.+    summary = res.get("summary") or {}+    ok = bool(res.get("success") or res.get("status") == "ok" or summary.get("ok", 0) > 0)+    reached = res.get("targets") or (["self"] if ok else [])     return {         "success": ok,-        "targets": (["self"] + peers) if peers else ["self"],-        "_hint": ("Toast sent" + (" to this machine AND all peer ADs (user may be on another computer)."-                  if peers else " to this machine (no peer ADs on the relay).")-                  + " This is the LAST RESORT - only use after exhausting programmatic options "-                  "(UIA background clicks, seat auto-resolve, warm-SSO sign-in). Now WAIT and poll "+        "via": "ad_client:direct(all)",+        "targets": reached,+        "_hint": ("Toast fanned out to ALL connected desktops (the user's machine included) via the "+                  "in-process AD direct API. This is the LAST RESORT - only use after exhausting "+                  "programmatic options (UIA background clicks, seat auto-resolve, warm-SSO sign-in), "+                  "and only when the box is ACTUALLY ready for the user to act. Now WAIT and poll "                   "fusion_readiness for the state to clear; do not re-toast within a few minutes."),     }