← Commit history

1.9.142: #49 fresh-account mint fallback + typed no_cloud_project

John Lauer ·35bc4db474 ·1mo ago ·parent 6247300
6 files changed +60−14
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.9.141\ No newline at end of file+1.9.142\ 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.141",-  "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.141/adom-bridge-fusion-v1.9.141.zip",-  "sha256": "a82f18ed2897830c3aea07a698002ee4170f2dff41b1e1605c0df1dd9a711fe9",-  "size": 475671,+  "version": "1.9.142",+  "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.142/adom-bridge-fusion-v1.9.142.zip",+  "sha256": "cf25ddf03ec26d76c5e307efae3ab6d4c9fe460a8bdc3a16d7fb9dc52d6ca829",+  "size": 476504,   "verbPrefixes": [     "fusion_"   ],
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.9.141",+  "version": "1.9.142",   "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.161",+  "version": "1.9.162",   "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.161",+  "version": "1.9.162",   "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+43
@@ -3660,7 +3660,34 @@ def _orchestrate_make_3d_package(args: dict) -> dict:         "    if ok: proj=p2; break\n"         "   if proj: break\n"         " except Exception as e: res['projErr']=str(e)[:60]\n"+        # FRESH-ACCOUNT FALLBACK (#49, jlauer12 2026-08-22): a brand-new Autodesk account has+        # neither the Adom default-upload project nor one named 'Main', so the targeted search+        # above leaves proj=None and `proj.rootFolder` used to leak a raw AttributeError+        # ('NoneType' has no attribute 'rootFolder'). Doctrine: don't just NAME the gap - fill+        # it. Take ANY healthy project (rootFolder probe, since fresh installs also throw+        # InternalValidationError id.size() on poisoned entries), else CREATE an 'Adom'+        # project in the first hub that allows it. Only if all of that fails do we surface+        # the typed no_cloud_project error below.+        "if not proj:\n"+        " try:\n"+        "  hubs=app.data.dataHubs\n"+        "  for hi in range(hubs.count):\n"+        "   ps=hubs.item(hi).dataProjects\n"+        "   for pj2 in range(ps.count):\n"+        "    try:\n"+        "     p2=ps.item(pj2); p2.rootFolder\n"+        "     proj=p2; break\n"+        "    except Exception: continue\n"+        "   if proj: break\n"+        "  if not proj:\n"+        "   for hi in range(hubs.count):\n"+        "    try:\n"+        "     proj=hubs.item(hi).dataProjects.add('Adom'); break\n"+        "    except Exception as e: res['createErr']=str(e)[:60]\n"+        " except Exception as e: res['projErr2']=str(e)[:60]\n"+        "if not proj: res['errorCode']='no_cloud_project'\n"         "try:\n"+        " if proj is None: raise RuntimeError('no usable cloud project on this account')\n"         " rf=proj.rootFolder\n"         f" wsf=_sub(_sub(rf,'Adom AI Workspace'),'{task}')\n"         f" doc.saveAs('{name}', wsf, '3d package (footprint+chip)', '')\n"@@ -3702,6 +3729,22 @@ def _orchestrate_make_3d_package(args: dict) -> dict:                 "before": before_shot, "after": after_shot,                 "_hint": "Saved DIRECTLY to the cloud workspace - no upload step needed. "                          "Bind this wip_urn into the library's <packages3d>."}+    if isinstance(res, dict) and res.get("errorCode") == "no_cloud_project":+        # #49 (fresh Autodesk account): name the ACTUAL cause with a typed code instead of+        # leaking 'NoneType has no attribute rootFolder'. The script above already tried+        # every hub for ANY healthy project AND tried to create an 'Adom' project.+        _detail = {k: res.get(k) for k in ("projErr", "projErr2", "createErr") if res.get(k)}+        return {"success": False, "errorCode": "no_cloud_project",+                "error": "3D minting uploads an .f3d to Autodesk cloud storage, and this "+                         "account has no usable cloud project (typical of a brand-new "+                         "Autodesk account). The bridge searched every hub for any healthy "+                         "project and also tried to CREATE an 'Adom' project; all failed: "+                         + (str(_detail) if _detail else "(no per-step detail)"),+                "before": before_shot, "after": after_shot,+                "_hint": "This is account setup, not a broken mint. Open Fusion's Data Panel "+                         "once (a fresh account provisions its default project on first "+                         "touch), or create any project in the hub, then re-run. "+                         "fusion_list_cloud_projects shows what the account can see."}     if not f3d_path or not str(f3d_path).endswith(".f3d"):         # Carry the add-in's OWN error up: res={} with the script error dropped on the         # floor cost a whole diagnosis round (2026-08-21 - the real story was Fusion being