app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
← Commit history
v0.9.119: point-release version blindness fixed in ALL THREE places - detection ranks installs by probed kicad-cli X.Y.Z (a per-user 10.0.5 now beats a Program Files 10.0.1), check_for_updates compares full versions, upgrade's post-install check too; nudge cache invalidated on upgrade success
7 files changed
+57−10
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.118+0.9.119
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.118",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.118/adom-bridge-kicad-v0.9.118.zip",- "sha256": "452876fd32c941336525eb3474e41efbccb157020e603c7548df19d3a1cbfdbf",- "size": 410595,+ "version": "0.9.119",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.119/adom-bridge-kicad-v0.9.119.zip",+ "sha256": "cb4640fe59796e8355e56a175c50c31fe568596e9b6d97e8c96710f3caf58579",+ "size": 411171, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-16T13:50:05Z",+ "released_at": "2026-08-16T14:27:29Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.119.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.118",+ "version": "0.9.119", "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-bridge", "author": "Adom Inc.",
handlers/upgrade.py+15−2@@ -100,9 +100,19 @@ def download_url(version: str) -> str: return _DL_URL.format(v=version) +def invalidate_installed_version_cache() -> None:+ """Call after a successful kicad_upgrade: the cached kicad-cli X.Y.Z is stale."""+ _nudge_cache["installed_full"] = None+ _nudge_cache["claimed"] = 0.0 # let the nudge re-evaluate promptly++ def handle_check_for_updates(kicad_info: dict, args: dict) -> dict: """Read-only: is a newer KiCad available, and does the current one have the IPC API?""" current = kicad_info.get("version") if kicad_info else None+ if current:+ full = _installed_full_version(kicad_info)+ if full:+ current = full # "10.0" would compare stale against "10.0.5" forever latest, src = latest_stable_version() cur_t = kicad_detect._version_tuple(current) if current else (0,) lat_t = kicad_detect._version_tuple(latest)@@ -417,9 +427,12 @@ def handle_upgrade(kicad_info: dict, args: dict) -> dict: "_hint": "If a UAC prompt appeared, approve it; or run the downloaded installer manually.", } - # Confirm by re-scanning installed versions.+ # Confirm by re-scanning installed versions — compare FULL versions+ # (kicad-cli X.Y.Z): the "10.0" detection string can never match a+ # "10.0.5" target, which made successful point-release installs report+ # as failures (AdomLapper, 2026-08-16). after = kicad_detect.detect_all_kicad_versions()- installed = [v["version"] for v in after]+ installed = [v.get("fullVersion") or v["version"] for v in after] now_has = any( kicad_detect._version_tuple(v) >= kicad_detect._version_tuple(target) for v in installed
kicad_detect.py+30−1@@ -718,7 +718,11 @@ def _win_detect_all() -> list[dict]: except (OSError, PermissionError): continue - found.sort(key=lambda info: _version_tuple(info["version"]), reverse=True)+ for info in found:+ fv = probe_full_version(info.get("kicad_cli_exe"))+ info["fullVersion"] = fv or info.get("version")+ found.sort(key=lambda info: _version_tuple(info.get("fullVersion") or info["version"]),+ reverse=True) return found @@ -866,6 +870,31 @@ def _mac_detect_all() -> list[dict]: # ║ PUBLIC API (cross-platform) ║ # ╚═══════════════════════════════════════════════════════════════════════════╝ +_full_version_cache: dict = {}+++def probe_full_version(cli_exe) -> str:+ """Full X.Y.Z from `kicad-cli version` (cached per path per boot). The detection+ string is only major.minor ("10.0"), which cannot distinguish point releases —+ that blindness bit three separate call sites on 2026-08-16."""+ key = str(cli_exe or "")+ if key in _full_version_cache:+ return _full_version_cache[key]+ v = ""+ try:+ import subprocess+ if key and Path(key).exists():+ out = subprocess.run([key, "version"], capture_output=True, text=True,+ timeout=15).stdout+ m = re.search(r"(\d+\.\d+\.\d+)", out or "")+ if m:+ v = m.group(1)+ except Exception:+ pass+ _full_version_cache[key] = v+ return v++ def detect_all_kicad_versions() -> list[dict]: """Discover every installed KiCad version on the current platform. Returns a list sorted newest first. Empty list if KiCad isn't installed."""
server.py+5@@ -627,6 +627,11 @@ def dispatch_command(command: str, args: dict) -> dict: if command == "upgrade": result = handler(kicad_info, args) if result.get("success") or result.get("upgraded"):+ try:+ from handlers.upgrade import invalidate_installed_version_cache+ invalidate_installed_version_cache()+ except Exception:+ pass all_kicad_versions = detect_all_kicad_versions() if all_kicad_versions: kicad_info = all_kicad_versions[0]