← Commit history

Update 4 file(s)

John Lauer ·563f9bbe38 ·1mo ago ·parent 109b88b
4 files changed +87−8
BRIDGE_VERSION+1−1
@@ -1 +1 @@-0.9.202\ No newline at end of file+0.9.203\ No newline at end of file
adom-bridge-kicad-manifest.json+5−5
@@ -1,15 +1,15 @@ {   "manifest_version": 1,   "name": "kicad",-  "version": "0.9.202",-  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.202/adom-bridge-kicad-v0.9.202.zip",-  "sha256": "da428b6cb0ecff185fa43e6918487362371f8b0039d3abaac2af3783755f13fe",-  "size": 471755,+  "version": "0.9.203",+  "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.203/adom-bridge-kicad-v0.9.203.zip",+  "sha256": "6a11d4fb41c136ac77a2b31c9bc9be77a7c8517f57c57544855671a0084b5275",+  "size": 472907,   "verbPrefixes": [     "kicad_"   ],   "healthEndpoint": "/status",-  "released_at": "2026-08-20T11:05:00Z",+  "released_at": "2026-08-20T11:30:00Z",   "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png",   "languages": [     "Python",
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "kicad",   "displayName": "KiCad EDA",-  "version": "0.9.202",+  "version": "0.9.203",   "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/kicad_ui.py+80−1
@@ -73,7 +73,85 @@ VK_MAP = {     "f9": 0x78, "f10": 0x79, "f11": 0x7A, "f12": 0x7B, } -SCREENSHOT_DIR = "C:/tmp/adom-desktop-screenshots"+def _screenshot_dir() -> str:+    """Where this bridge writes its captures.++    Wiki issue #40 (John, 2026-08-20). This used to be a hardcoded+    C:/tmp/adom-desktop-screenshots. Two problems: `adom-desktop` is a RETIRED+    product name (renamed to Adom Bridge in 2.0.0), so a fresh directory under+    the old name was the last place it was still propagating - a user auditing+    their disk found a folder for an app that no longer exists; and C:/tmp is+    not a Windows convention at all. Now it lives beside the other bridge caches+    under the current name, matching what pup does."""+    base = os.environ.get("LOCALAPPDATA")+    if base:+        return os.path.join(base, "Adom Bridge", "bridges-cache", "kicad", "screenshots")+    return os.path.join(os.environ.get("TEMP") or "/tmp", "adom-kicad-shots")+++SCREENSHOT_DIR = _screenshot_dir()++# Retained so the janitor can drain what earlier versions already wrote.+_LEGACY_SCREENSHOT_DIRS = ("C:/tmp/adom-desktop-screenshots", "C:/tmp/ad-shots")++_SHOT_MAX_AGE_SEC = 48 * 3600   # two days of history is plenty to debug with+_SHOT_MAX_FILES = 300           # and a hard ceiling for a heavy test day+_last_prune = 0.0+++def prune_screenshots(force: bool = False) -> dict:+    """Keep the capture directory bounded. Nothing else prunes it - ab's janitor+    covers ab's OWN dirs and should not be expected to know about ours.++    Deletes by age first, then oldest-first if still over the file ceiling, and+    drains the retired directories on the way. Runs at most once every 10+    minutes so it never adds latency to a burst of captures."""+    global _last_prune+    now = time.time()+    if not force and (now - _last_prune) < 600:+        return {"skipped": "ran recently"}+    _last_prune = now+    removed = 0+    freed = 0+    for d in (SCREENSHOT_DIR,) + _LEGACY_SCREENSHOT_DIRS:+        try:+            if not os.path.isdir(d):+                continue+            legacy = d != SCREENSHOT_DIR+            entries = []+            for name in os.listdir(d):+                fp = os.path.join(d, name)+                try:+                    st = os.stat(fp)+                except Exception:+                    continue+                if not os.path.isfile(fp):+                    continue+                entries.append((st.st_mtime, st.st_size, fp))+            entries.sort()+            # A retired directory is drained entirely; the live one keeps a window.+            doomed = list(entries) if legacy else [+                e for e in entries if (now - e[0]) > _SHOT_MAX_AGE_SEC]+            if not legacy:+                keep = [e for e in entries if e not in doomed]+                if len(keep) > _SHOT_MAX_FILES:+                    doomed += keep[: len(keep) - _SHOT_MAX_FILES]+            for _mt, size, fp in doomed:+                try:+                    os.remove(fp)+                    removed += 1+                    freed += size+                except Exception:+                    pass+            if legacy:+                try:+                    os.rmdir(d)+                except Exception:+                    pass+        except Exception:+            pass+    return {"removed": removed, "freedMB": round(freed / 1048576.0, 1),+            "dir": SCREENSHOT_DIR}  # KiCad window title keywords (wxWidgets windows use class wxWindowNR) KICAD_TITLE_KEYWORDS = [@@ -423,6 +501,7 @@ def _screenshot_hwnd(hwnd: int, label: str = "", max_dim: int = 1568) -> dict:     user32.ReleaseDC(hwnd, hdc_screen)      os.makedirs(SCREENSHOT_DIR, exist_ok=True)+    prune_screenshots()     timestamp = int(time.time() * 1000)     # Slugify the label so filenames have NO spaces/punctuation (clean for a     # cloud caller to pull). v0.8.8: "pcb_editor pic_programmer Read Only" -> "pcb-editor-pic-programmer-read-only".