← Commit history

v0.9.61: kicad_export_molecule — one-shot molecule export pack (STEP + silk renders + sch/pro discovery + container next-steps); capabilities note KiCad-11 schematic IPC

John Lauer ·8e0e36f8de ·3mo ago ·parent 78f6d99
7 files changed +148−11
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.9.10+0.9.61
adom-bridge-kicad-manifest.json+6−6
@@ -1,19 +1,19 @@ {   "manifest_version": 1,   "name": "kicad",-  "version": "0.9.60",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.60/adom-bridge-kicad-v0.9.60.zip",-  "sha256": "675f2dd7c44d4ca3fe2f1735fe54166079d0e1b09a3a1f9fee95c11840c48c65",-  "size": 646046,+  "version": "0.9.61",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.61/adom-bridge-kicad-v0.9.61.zip",+  "sha256": "11387c89dd960e16797c42a1db4972f0547f24ffd656da225b71be8e5e103c7b",+  "size": 500594,   "verbPrefixes": [     "kicad_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-07-04T14:44:55Z",+  "released_at": "2026-07-15T13:12:16Z",   "hero": "https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/kicad-hero.png",   "languages": [     "Python",     "PowerShell"   ],   "updateManifestUrl": "https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/adom-bridge-kicad-manifest.json"-}+}\ No newline at end of file
adom-bridge-kicad-v0.9.61.zipadded
⋯ 1 unchanged line ⋯
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "kicad",   "displayName": "KiCad EDA",-  "version": "0.9.60",+  "version": "0.9.61",   "description": "Reverse bridge for KiCad \u2014 board/schematic introspection, lint via kicad-cli, plugin install, multi-instance probe, in-process DRC.",   "homepage": "https://wiki.adom.inc/adom/adom-desktop",   "author": "Adom Inc.",
capabilities.py+7−3
@@ -25,9 +25,13 @@ public KiCad IPC-API roadmap):     The schematic/symbol editor has NO IPC handler yet, so opening a     *symbol* on the canvas stays assisted (Win32) automation.   * KiCad 11 (when it ships) → SWIG bindings removed; IPC is the only-    Python path and is expected to broaden to the schematic/symbol editor.-    When it does, symbol delivery flips from "assisted" to "ipc" with no-    caller change — they just read `automation.symbol`.+    Python path and broadens to the schematic editor. Confirmed against+    kipy (kicad-python): `KiCad.get_schematic()` is tagged "Added in …+    (KiCad 11)" — the schematic object is NOT in KiCad 10.x, so on 10.x+    symbol/schematic work stays assisted (Win32) automation. When 11 lands,+    symbol delivery flips from "assisted" to "ipc" with no caller change —+    they just read `automation.symbol`. (Verified 2026-07: get_board() is+    the only document object exposed by kipy on 10.0.x.)  The IPC API also requires the user to ENABLE the API server (Preferences > Plugins > "Enable KiCad API server"); we detect that from
handlers/export_molecule.pyadded+126
@@ -0,0 +1,126 @@+"""kicad_export_molecule — one-shot "molecule export pack" for a KiCad board.++The Adom molecule pipeline (container side) is:+    STEP  →  step2glb (color-preserving GLB)  →  adom-molecule create+             --glb ... --pcb ... --sch ... --pro ...   →  Hydrogen molecule+             (+ optionally a wiki.adom.inc component page)++adom-molecule REQUIRES four files for a KiCad source: .glb, .kicad_pcb,+.kicad_sch and .kicad_pro. The GLB comes from the STEP via step2glb *in the+container*; everything else lives here on the Windows host next to the board.++This verb does the entire desktop-side half in one call:+  1. export the board's STEP (geometry + component models),+  2. render silkscreen top/bottom PNGs when `kicad-cli pcb render` exists+     (KiCad 9+; optional extras for the molecule page),+  3. locate the sibling .kicad_sch / .kicad_pro by the board's stem,+  4. return a single manifest of host paths + the exact container commands+     to finish the pipeline.++The caller then pull_file's the manifest paths and runs the printed commands.+No container tools are shelled from here — the bridge stays desktop-only.+"""++import os+import subprocess+from pathlib import Path++from .export import _run_pcb_export+++def handle_export_molecule(kicad_info: dict, args: dict) -> dict:+    if not kicad_info.get("installed"):+        return {+            "success": False,+            "error": "KiCad not installed",+            "_hint": "Install KiCad first (kicad_upgrade), then retry.",+        }++    file_path = args.get("filePath", "")+    if not file_path:+        return {"success": False, "error": "No filePath specified (the .kicad_pcb)"}+    pcb_path = Path(file_path)+    if not pcb_path.exists():+        return {+            "success": False,+            "error": f"PCB file not found: {file_path}",+            "_hint": "Path must exist on the Windows host. send_files it first if it lives in Docker.",+        }++    out_dir = args.get("outputDir") or str(pcb_path.parent / "molecule_output")+    os.makedirs(out_dir, exist_ok=True)++    result: dict = {"success": True, "data": {}}+    missing: list = []++    # 1) STEP (reuse the standard export; honors its own error paths)+    step_res = _run_pcb_export(+        kicad_info,+        {"filePath": str(pcb_path), "outputDir": out_dir},+        "step",+        "STEP",+    )+    if not step_res.get("success"):+        return {+            "success": False,+            "error": f"STEP export failed: {step_res.get('error')}",+            "_hint": "The STEP is mandatory for the molecule GLB — fix this first.",+        }+    step_path = step_res["data"]["output_path"]+    result["data"]["step"] = step_path++    # 2) Silkscreen renders (optional; needs `kicad-cli pcb render`, KiCad 9+)+    cli_exe = kicad_info.get("kicad_cli_exe")+    silk = {}+    for side in ("top", "bottom"):+        png = os.path.join(out_dir, f"{pcb_path.stem}-silk-{side}.png")+        try:+            r = subprocess.run(+                [cli_exe, "pcb", "render", "--side", side,+                 "--background", "transparent", "--output", png, str(pcb_path)],+                capture_output=True, text=True, timeout=180,+            )+            if r.returncode == 0 and Path(png).exists():+                silk[side] = png+            else:+                missing.append(f"silk-{side} (kicad-cli pcb render rc={r.returncode})")+        except Exception as e:  # old KiCad without `pcb render`, timeout, …+            missing.append(f"silk-{side} ({e})")+    result["data"]["silkscreen"] = silk++    # 3) Sibling project files by stem — adom-molecule needs sch + pro+    sch = pcb_path.with_suffix(".kicad_sch")+    pro = pcb_path.with_suffix(".kicad_pro")+    result["data"]["pcb"] = str(pcb_path)+    result["data"]["sch"] = str(sch) if sch.exists() else None+    result["data"]["pro"] = str(pro) if pro.exists() else None+    for label, p in (("sch", sch), ("pro", pro)):+        if not p.exists():+            missing.append(f"{label} ({p.name} not next to the board — adom-molecule requires it)")++    # 4) The exact container-side finish+    name = args.get("name") or pcb_path.stem+    result["data"]["nextSteps"] = [+        f"pull_file the paths in data (step/pcb/sch/pro/silkscreen) to the container",+        f"step2glb convert <step> --out /tmp/{pcb_path.stem}.glb",+        (+            f"adom-molecule create --source kicad --name \"{name}\" --owner <owner> "+            f"--description \"<desc>\" --glb /tmp/{pcb_path.stem}.glb "+            f"--pcb <pcb> --sch <sch> --pro <pro>"+            + (" --silk-top <silk-top> --silk-bottom <silk-bottom>" if silk else "")+        ),+    ]+    if missing:+        result["data"]["missing"] = missing+    result["output"] = (+        f"Molecule export pack in {out_dir}: STEP"+        + (f" + silk({','.join(silk)})" if silk else "")+        + (f"; MISSING: {'; '.join(missing)}" if missing else " — complete")+    )+    result["_hint"] = (+        "Desktop half of the molecule pipeline is done. pull_file everything in "+        "data, then run data.nextSteps in the container (step2glb → adom-molecule "+        "create). adom-molecule REQUIRES glb+pcb+sch+pro; silk PNGs are optional "+        "polish for the molecule page."+    )+    return result
server.py+7
@@ -56,6 +56,9 @@ from handlers.export import (     handle_export_gerber, handle_export_pdf, handle_export_svg,     handle_export_step, handle_export_bom_csv, )+# v0.9.61+: one-shot desktop half of the Adom molecule pipeline (STEP + silk+# renders + sibling sch/pro discovery + container next-steps manifest).+from handlers.export_molecule import handle_export_molecule # v0.9.10+: check/upgrade KiCad via the OFFICIAL downloads.kicad.org installer # (NOT winget, which lags the real release). check_for_updates is read-only; # upgrade silent-installs the official signed NSIS build.@@ -320,6 +323,9 @@ _VERB_CATALOG = {     "export_step": {"summary": "Export a STEP 3D model from a board.", "long": False,         "hint": "Absolute board path + output; exports a STEP assembly via kicad-cli.",         "related": ["kicad_open_3d_viewer", "kicad_export_gerber"], "pitfalls": ["only components with 3D models attached appear in the STEP"]},+    "export_molecule": {"summary": "One-shot molecule export pack: STEP + silk renders + sch/pro discovery for the Adom molecule pipeline.", "long": True,+        "hint": "Absolute board path; exports STEP (+ silkscreen top/bottom PNGs when kicad-cli pcb render exists), finds the sibling .kicad_sch/.kicad_pro, and returns data.nextSteps — the exact container commands (step2glb → adom-molecule create) to finish.",+        "related": ["kicad_export_step", "kicad_export_svg"], "pitfalls": ["adom-molecule requires glb+pcb+sch+pro — check data.missing before running the container half", "silk renders need KiCad 9+ (kicad-cli pcb render); older KiCads skip them gracefully"]},     "export_bom_csv": {"summary": "Export a BOM CSV from a schematic.", "long": False,         "hint": "Absolute schematic path + output; writes a BOM CSV via kicad-cli.",         "related": ["kicad_open_schematic", "kicad_export_gerber"], "pitfalls": ["needs kicad-cli (KiCad >= 7)"]},@@ -473,6 +479,7 @@ COMMAND_HANDLERS = {     "export_pdf": handle_export_pdf,     "export_svg": handle_export_svg,     "export_step": handle_export_step,+    "export_molecule": handle_export_molecule,     "export_bom_csv": handle_export_bom_csv,     # v0.9.10+: KiCad version check + upgrade via the official downloads.kicad.org     # installer (read-only check; silent /S install). Exposed as kicad_check_for_updates