← Commit history
BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.9.106+1.9.107
adom-bridge-fusion-manifest.json+4−4
@@ -1,10 +1,10 @@ {     "manifest_version": 1,     "name": "fusion360",-    "version": "1.9.106",-    "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.121/adom-bridge-fusion-v1.9.106.zip",-    "sha256": "3e0fe6e2fc817a76a2c2e62f02c0201fd98f1bba0ea9e3496b043e1865c90c64",-    "size": 448670,+    "version": "1.9.107",+    "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.122/adom-bridge-fusion-v1.9.107.zip",+    "sha256": "452f2194983abdfc6fc1f0724c353d6c28e0e952c729f74cc66010eef3c2ea4d",+    "size": 442430,     "verbPrefixes": [         "fusion_"     ],
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "fusion360",   "displayName": "Autodesk Fusion 360",-  "version": "1.9.106",+  "version": "1.9.107",   "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.",
dashboard/Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.121"+version = "1.9.122" edition = "2021"  [dependencies]
install.sh+1−1
@@ -21,7 +21,7 @@ echo "Installed fusion-bridge skills: $(ls "$PKG_DIR/skills" 2>/dev/null | tr '\ # binary (the three-artifact pattern: bridge zip -> ab, THIS pkg -> container skills + # this download, page media -> wiki). Per the wiki's PKG_VS_RELEASE policy, binaries are # platform-tagged RELEASE assets, never tarball content - the installer fetches them.-DASH_VERSION="1.9.121"+DASH_VERSION="1.9.122" DASH_URL="https://wiki.adom.inc/download/adom/fusion-bridge/${DASH_VERSION}/fusion-dashboard" DEST="" if [ -w /usr/local/bin ]; then DEST=/usr/local/bin
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "fusion-bridge",-  "version": "1.9.121",+  "version": "1.9.122",   "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.121",+  "version": "1.9.122",   "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+65−67
@@ -9029,86 +9029,84 @@ COMMAND_HANDLERS["prove_library"] = _handle_prove_library   +def _find_adom_lbr() -> str:+    """Locate adom-lbr on THIS box (the canonical KiCad->EAGLE converter, adom/adom-lbr)."""+    import shutil as _sh+    hit = _sh.which("adom-lbr") or _sh.which("adom-lbr.exe")+    if hit:+        return hit+    la = os.environ.get("LOCALAPPDATA", "")+    for c in ([os.path.join(la, "Programs", "adom-lbr", "adom-lbr.exe"),+               os.path.join(la, "adom-lbr", "adom-lbr.exe")] if la else []):+        if os.path.exists(c):+            return c+    return ""++ def _handle_import_kicad(fusion_info: dict, args: dict) -> dict:-    """Ingest KiCad symbol/footprint files and BUILD or PATCH a valid .lbr (issue #43).--    KiCad is the FUNDAMENTAL symbol/footprint representation at Adom; the .lbr is derived,-    and a derived file can be missing, stale, or half-generated. This verb makes the .lbr an-    optimization instead of a prerequisite - the same posture bind_library_3d already takes-    for STEP.--    args:-      kicadFootprintPath - Windows path to a .kicad_mod   (optional)-      kicadSymbolPath    - Windows path to a .kicad_sym   (optional)-      libraryPath        - .lbr to PATCH if it exists, else where to WRITE the new library-                           (optional; defaults next to the footprint/symbol file)-      name, prefix       - optional overrides for the created deviceset--    PATCH fills only what is EMPTY (<packages></packages>, <connects/>) and never overwrites-    existing content. The concrete case: cr0603-fx-5601elf's .lbr had an empty <packages>-    while a correct .kicad_mod sat beside it, so every downstream verb refused honestly and-    uselessly. After this verb, that part just works.+    """Ingest KiCad symbol/footprint files and produce a valid .lbr (issue #43) - by+    DELEGATING to adom-lbr, the ecosystem's canonical converter.++    John, 2026-08-21: "just use adom-lbr as your converter" - instead of this bridge+    growing its own KiCad parser. adom-lbr owns the conversion, ships a linter whose+    checks name the exact failure this issue was filed about (empty-packages /+    empty-connects -> Fusion "No Components"), and round-trips KiCad, EAGLE and Altium.+    One converter, one set of bugs, one place to fix them.++    args: kicadSymbolPath, kicadFootprintPath (Windows paths), libraryPath (output,+    optional), name (optional override).     """-    import os as _os-    import kicad_lbr as _kl-    mod_p = (args.get("kicadFootprintPath") or "").replace("\\", "/")+    import subprocess as _sp     sym_p = (args.get("kicadSymbolPath") or "").replace("\\", "/")+    mod_p = (args.get("kicadFootprintPath") or "").replace("\\", "/")     lbr_p = (args.get("libraryPath") or "").replace("\\", "/")-    if not mod_p and not sym_p:+    if not sym_p and not mod_p:         return {"success": False, "errorCode": "kicad_source_required",-                "error": "Pass kicadFootprintPath and/or kicadSymbolPath.",-                "_hint": "Both are wiki first-class artifacts; stage them with send_files, "-                         "then call this with their Windows paths."}-    def _read(p, what):-        if not p:-            return None, None-        try:-            return open(p, "r", encoding="utf-8", errors="replace").read(), None-        except Exception as e:-            return None, {"success": False, "errorCode": "kicad_source_unreadable",-                          "error": "Could not read %s: %s (%s)" % (what, p, str(e)[:80])}-    mod_text, err = _read(mod_p, ".kicad_mod")-    if err:-        return err-    sym_text, err = _read(sym_p, ".kicad_sym")-    if err:-        return err+                "error": "Pass kicadSymbolPath and/or kicadFootprintPath."}+    tool = _find_adom_lbr()+    if not tool:+        return {"success": False, "errorCode": "adom_lbr_unavailable",+                "error": "adom-lbr (the canonical KiCad->EAGLE converter) is not installed "+                         "on this box, and this bridge deliberately does NOT convert KiCad "+                         "formats itself.",+                "_hint": ("Conversion is owned by adom/adom-lbr - one converter for the whole "+                          "ecosystem. From a CONTAINER: `adom-lbr generate --sym <.kicad_sym> "+                          "--fp <.kicad_mod> -o <out.lbr>` (auto-linted), then stage the .lbr "+                          "to this box (send_files, dest under %TEMP%) and use the fusion_show_* "+                          "verbs. A windows release asset of adom-lbr has been requested so this "+                          "verb can run it on-box.")}     if not lbr_p:-        base = (mod_p or sym_p).rsplit("/", 1)+        base = (sym_p or mod_p).rsplit("/", 1)         stem = base[-1].rsplit(".", 1)[0]         lbr_p = (base[0] + "/" if len(base) > 1 else "") + stem + ".lbr"-    mode = "patched" if _os.path.exists(lbr_p) else "created"+    cmd = [tool, "generate"]+    if sym_p:+        cmd += ["--sym", sym_p]+    if mod_p:+        cmd += ["--fp", mod_p]+    if args.get("name"):+        cmd += ["--name", str(args["name"])]+    cmd += ["-o", lbr_p]     try:-        if mode == "patched":-            original = open(lbr_p, "r", encoding="utf-8", errors="replace").read()-            new_text, report = _kl.patch_lbr(original, kicad_mod_text=mod_text,-                                             kicad_sym_text=sym_text, name=args.get("name"))-            if new_text == original:-                report["unchanged"] = True-            else:-                try:-                    open(lbr_p + ".bak", "w", encoding="utf-8").write(original)-                except Exception:-                    pass-                open(lbr_p, "w", encoding="utf-8").write(new_text)-        else:-            new_text, report = _kl.build_lbr(kicad_sym_text=sym_text, kicad_mod_text=mod_text,-                                             name=args.get("name"),-                                             prefix=args.get("prefix") or "U")-            open(lbr_p, "w", encoding="utf-8").write(new_text)+        r = _sp.run(cmd, capture_output=True, text=True, timeout=120)     except Exception as e:-        return {"success": False, "errorCode": "kicad_conversion_failed",-                "error": "Conversion failed: %s" % str(e)[:200]}+        return {"success": False, "errorCode": "adom_lbr_failed",+                "error": "adom-lbr did not run: %s" % str(e)[:150]}+    if r.returncode != 0:+        return {"success": False, "errorCode": "adom_lbr_failed",+                "error": "adom-lbr generate failed (exit %d): %s"+                         % (r.returncode, (r.stderr or r.stdout)[-300:]),+                "_hint": "adom-lbr auto-lints its output and exits 2 on lint failure - the "+                         "message above names the exact check that failed."}     names = _library_artifact_names(lbr_p)-    return {"success": True, "libraryPath": lbr_p, "mode": mode, "report": report,+    return {"success": True, "libraryPath": lbr_p, "converter": "adom-lbr",             "symbols": names.get("sym", []), "packages": names.get("pac", []),             "devicesets": names.get("dev", []), "has3d": bool(names.get("p3d")),-            "sources": {"kicadFootprint": mod_p or None, "kicadSymbol": sym_p or None},-            "_hint": ("%s %s from KiCad sources. fusion_show_symbol / show_footprint consume "-                      "it directly; bind the 3D with fusion_bind_library_3d {libraryPath, "-                      "stepPath} (has3d is %s), then fusion_prove_library captures the four "-                      "evidence frames. A .bak sits beside a patched file."-                      % (mode.capitalize(), lbr_p, bool(names.get("p3d"))))}+            "toolOutput": (r.stdout or "").strip()[-300:],+            "_hint": ("Generated by adom-lbr (lint-clean by construction). fusion_show_symbol / "+                      "show_footprint consume it directly; bind the 3D with "+                      "fusion_bind_library_3d {libraryPath, stepPath}, then "+                      "fusion_prove_library captures the four evidence frames.")}   COMMAND_HANDLERS["import_kicad"] = _handle_import_kicad
tools/release-files.txt−1
@@ -56,4 +56,3 @@ start.bat uninstall.sh handlers/taskbar_overlay.py resources/adom-overlay-32.png-kicad_lbr.py