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.63: demo steps one beat per call (data.nextCall) so it never hits AD's request budget; {all:true} for bulk
3 files changed
+27−12
adom-bridge-kicad-manifest.json+2−2@@ -3,8 +3,8 @@ "name": "kicad", "version": "0.9.63", "url": "https://wiki.adom.inc/download/adom/adom-desktop-kicad-bridge/0.9.63/adom-bridge-kicad-v0.9.63.zip",- "sha256": "ed093ac00af3560c3c0fe8e4d84bd4deaf475184cca1282a16dc0282a15add64",- "size": 351907,+ "sha256": "5373614086b6cb5f3143cba5f03b46c0a027bb64799c847c8c78f48500fe212d",+ "size": 352272, "verbPrefixes": [ "kicad_" ],
adom-bridge-kicad-v0.9.63.zip⋯ 1 unchanged line ⋯
handlers/demo.py+25−10@@ -397,23 +397,34 @@ def handle_demo(kicad_info: dict, args: dict) -> dict: return {"success": False, "error": f"unknown step '{step}'", "data": {"validSteps": STEPS}} prep = _prepare(kicad_info)- # Cold-start warm-up: launches eeschema so the editor steps take the fast- # in-process pathway instead of a cold WM_COMMAND that times out.- prep["warm"] = _warm_kicad(kicad_info, prep)++ # DEFAULT = one beat at a time. The full six-window tour takes ~90 s, which+ # blows AD's per-request budget and returns a timeout that looks like a broken+ # demo. Stepping also simply narrates better: say the line, screenshot, move on.+ # {"all": true} still runs the whole thing for non-interactive use.+ run_all = bool(args.get("all"))+ steps = STEPS if run_all else [step or STEPS[0]]++ # Warm eeschema only when starting the tour (Symbol Editor is hosted inside it,+ # and a cold WM_COMMAND misses its 10 s budget). Later beats reuse the warm app.+ if run_all or steps[0] == STEPS[0]:+ prep["warm"] = _warm_kicad(kicad_info, prep) import time- steps = [step] if step else STEPS results, failed = [], []- for s in steps:- r = _run_step(kicad_info, s, prep)+ for s_ in steps:+ r = _run_step(kicad_info, s_, prep) if not r.get("ok"): # one retry — a cold editor often misses its first budget time.sleep(3)- r = _run_step(kicad_info, s, prep)+ r = _run_step(kicad_info, s_, prep) r["retried"] = True- r["step"] = s+ r["step"] = s_ results.append(r) if not r.get("ok"):- failed.append(s)+ failed.append(s_)++ last = steps[-1]+ nxt = STEPS[STEPS.index(last) + 1] if last in STEPS and STEPS.index(last) + 1 < len(STEPS) else None done = [r["step"] for r in results if r.get("ok")] return {@@ -428,12 +439,16 @@ def handle_demo(kicad_info: dict, args: dict) -> dict: "warnings": prep.get("warnings"), "installedKiCadJustNow": installed_now, "warmedUp": (prep.get("warm") or {}).get("warmed"),+ "nextCall": (f'kicad_demo {{"step": "{nxt}"}}' if nxt else None),+ "remainingSteps": STEPS[STEPS.index(last) + 1:] if last in STEPS else [], "screenshotVerb": "kicad_screenshot_all", "cleanup": "kicad_close {\"force\":true}", }, "_hint": ( ("You just installed KiCad for them — say so, it lands well. " if installed_now else "")- + "This is a NARRATED tour — each entry in data.steps carries `title`, `say` (speak it, "+ + "This is a NARRATED tour, ONE BEAT PER CALL. Speak data.steps[0].say, screenshot the "+ "window named in .window, mention .pointOut, then call data.nextCall for the next "+ "beat. Each entry carries `title`, `say` (speak it, " "don't read JSON), `pointOut` (what's actually on screen) and `window` (match that " "title in kicad_screenshot_all to show it). Best flow: call kicad_demo with one " "`step` at a time (" + " -> ".join(STEPS) + "), say the line, screenshot that window, "