app
hello-python - sample bridge (Python)
Public Made by Adomby adom
Minimal third-party Adom Desktop bridge in ~80 lines of Python stdlib. Fork this as a starting point for your own bridge.
← Commit history
Modernize sample: 3 verbs, v1.3.0, ADOM_BIND_HOST, caller headers, _reportIssues, --ai-thread install (wiki #229)
1 file changed
+81−124
README.md+81−124@@ -1,124 +1,81 @@-# Adom Desktop - Hello Sample Bridge (Python)--------## What this is--`hello-python` is a **minimal third-party bridge** for Adom Desktop, written in ~80 lines of Python stdlib. It exists so you can install one command, run two verbs, and have a complete mental model of what writing a bridge actually involves — before you commit to integrating your real tool (Altium, MATLAB, an oscilloscope, an inventory system, whatever).--Pair it with its twin [`hello-rust`](https://wiki.adom.inc/adom/adom-desktop-hello-rust-bridge) (same surface, different language) for a side-by-side comparison of the two implementation flavors Adom Desktop supports: `kind: "python"` (interpreted) vs. `kind: "exe"` (native single-binary).--If you're getting started, also read the [bridge SDK guide](https://wiki.adom.inc/adom/adom-desktop-bridges) for the `bridge.json` schema and packaging conventions.--## Try it in 30 seconds--```bash-# 1. Install from the wiki (anonymous, no GitHub account needed)-adom-desktop bridge_install '{"manifestUrl":"https://wiki.adom.inc/static/apps/adom-desktop/hello-python-bridge-manifest.json"}'--# 2. Ping it (auto-spawns the bridge process)-adom-desktop hellopy_ping-# → {"success":true,"output":"Hello from the Python sample bridge v1.2.0!","language":"python",...}--# 3. Echo something back-adom-desktop hellopy_echo '{"message":"world"}'-# → {"success":true,"output":"echo (python): world","echoed":"world","language":"python"}--# 4. Confirm it's registered-adom-desktop bridge_list # look for "hello-python" with verbs hellopy_*--# 5. Uninstall when done-adom-desktop bridge_uninstall '{"name":"hello-python"}'-```--The bridge process auto-spawns on the first `hellopy_*` call, listens on an OS-assigned ephemeral port (v1.8.31+ dynamic port allocation — no collision with any other bridge), and is killed cleanly on `bridge_uninstall` or app shutdown.--## What's in the box--```-hello-python/-├── bridge.json ← manifest (verb prefixes, spawn config, platforms)-├── BRIDGE_VERSION ← semver, kept in sync with bridge.json-├── server.py ← ~80 lines, http.server.BaseHTTPRequestHandler-└── README.md ← lifecycle notes-```--That's the entire bridge. No external pip dependencies — just the Python stdlib.--## The two endpoints every bridge exposes--| Endpoint | When | What it returns |-|---|---|---|-| `GET /status` | Adom Desktop polls this after spawn to confirm the bridge is alive | `{"ok": true, "bridge": "hello-python", "version": "...", "uptimeSec": N}` |-| `POST /command` | Every CLI verb call routes through here | `{"success": bool, "output": ..., "error": ...}` (response shape is conventional, not enforced) |--## How verb routing works--1. `bridge.json` declares `verbPrefixes: ["hellopy_"]`-2. Adom Desktop's registry records that `hellopy_*` belongs to this bridge-3. When you type `adom-desktop hellopy_ping`, the Tauri runtime:- - Spawns `python server.py --port <ephemeral>` if not already running- - Polls `/status` until ready- - POSTs `{"command":"hellopy_ping","args":{}}` to `/command`- - Streams the JSON response back through the CLI--## The two verbs--| Verb | Args | Returns |-|---|---|---|-| `hellopy_ping` | (none) | `{success, output, bridge, language: "python", version, uptimeSec, _hint}` |-| `hellopy_echo` | `{"message": "<str>"}` | `{success, output, echoed, language: "python"}` |--Try `adom-desktop status hellopy_ping` to see the AI-friendly help-map entry that drives Docker Claude usage.--## Forking for your own bridge--The fastest way to get to a real bridge:--```bash-# 1. Get the source (anonymous — no GitHub account needed)-curl -O https://wiki.adom.inc/static/apps/adom-desktop/hello-python-bridge.zip-unzip hello-python-bridge.zip && cd hello-python--# 2. Rename the bridge end-to-end-# - bridge.json: change "name", "displayName", "verbPrefixes", "verbs"-# - server.py: change __version__, rename the if/elif command branches-# - BRIDGE_VERSION: reset to 0.1.0--# 3. Replace the verb implementations with calls into your tool's SDK-# (Altium COM, MATLAB Engine, instrument SCPI, your REST API, etc.)--# 4. Test locally without packaging:-python server.py --port 8890 # in one terminal-adom-desktop bridge_install '{"manifestUrl":"file:///abs/path/to/your/bridge.json"}'--# 5. Package + ship — see the SDK guide-```--The full source tree (with the dynamic-port v1.8.31 wiring intact) is at [`scripts/sample-bridges/hello-python/`](https://github.com/adom-inc/adom-desktop/tree/main/scripts/sample-bridges/hello-python) in the Adom Desktop repo, mirroring what `bridge_install` extracts to your cache dir.--## When Python is the right choice--Pick `hello-python` (vs. the Rust flavor) when:--- **Your tool has Python bindings.** KiCad, Fusion 360, OpenCV, NumPy ecosystem — Python is the natural shim.-- **I/O-bound work.** REST calls, file walks, slow vendor SDKs — Python's overhead is invisible.-- **Fast iteration.** No compile step. `Ctrl+S` then re-run.-- **End users already have Python.** Engineers running Adom Desktop on a workstation typically have it.--Pick [`hello-rust`](https://wiki.adom.inc/adom/adom-desktop-hello-rust-bridge) when you need a single static binary, no runtime install, type safety, or CPU-bound performance.--## License--MIT. Fork freely, sell what you build on top.--## See also--- [Adom Desktop bridge SDK guide](https://wiki.adom.inc/adom/adom-desktop-bridges) — `bridge.json` schema, packaging, lifecycle-- [`hello-rust`](https://wiki.adom.inc/adom/adom-desktop-hello-rust-bridge) — Rust port of this same surface-- [Bridges registry](https://wiki.adom.inc/adom/adom-desktop-bridges-registry) — community-maintained list of installable bridges-- [Reference bridges: KiCad, Fusion 360, Puppeteer](https://wiki.adom.inc/adom/adom-desktop-bridges-registry) — full-complexity production examples+# Hello sample bridge — Python flavor + +One of two parallel reference bridges for the Adom Desktop bridge SDK. The Python flavor is a complete working bridge in ~140 lines of stdlib — no `pip install`, no virtualenv, no external dependencies. **Fork this when Python is the natural fit** (vendor SDKs with Python bindings: Altium Designer scripting, MATLAB Engine, KiCad's `pcbnew`, instrument vendor wrappers like `pyvisa`, etc.). Kept in lock-step with [`skills/BRIDGE_SDK.md`](../../../skills/BRIDGE_SDK.md) — every current author contract is demonstrated in `server.py`. + +The Rust sibling lives at [`scripts/sample-bridges/hello-rust/`](../hello-rust/) — same surface, different verb prefix (`hellors_` vs `hellopy_`). Both use `port: 0` (v1.8.31+ dynamic OS-assigned ports), so they can be installed simultaneously with no port-collision worry. + +## What it does + +Three verbs: + +- `hellopy_ping` → returns `{"success": true, "output": "Hello from the Python sample bridge v1.3.0!", "language": "python", ...}` +- `hellopy_echo` with `{"message": "..."}` → echoes the message back as `"echo (python): <msg>"` +- `hellopy_describe` → the self-doc catalog AD renders in its Verbs tab (one entry per verb, with hint/related/pitfalls) + +It also demonstrates the current author contracts you should copy: loopback bind via `ADOM_BIND_HOST`, the self-reported status-chip LED, rich `_hint`s, caller-provenance logging (it prints which AI thread + container drove each call), and a throttled `_reportIssues` line inviting bug reports. + +## How it gets installed end-to-end + +Relay calls (from a cloud container / galliaApril) each need `--ai-thread "<your thread name>"` — AD refuses a relayed command with no caller identity (`errorCode: caller_identity_required`). Shown on the first line; add it to every relayed call. A LOCAL `adom-desktop-cli.exe` on the same PC as AD does not need it. + +```bash +# (from galliaApril, or any machine with adom-desktop CLI on PATH) +adom-desktop --ai-thread "my-thread" bridge_install '{"manifestUrl":"https://wiki.adom.inc/api/v1/pages/adom-desktop-hello-python-bridge/files/adom-bridge-hello-python-manifest.json"}' + +# Confirm it's loaded +adom-desktop --ai-thread "my-thread" bridge_list +# → "hello-python" appears alongside the bundled bridges + +# Call a verb +adom-desktop --ai-thread "my-thread" hellopy_ping +adom-desktop --ai-thread "my-thread" hellopy_echo '{"message":"world"}' + +# Uninstall when done +adom-desktop --ai-thread "my-thread" bridge_uninstall '{"name":"hello-python"}' +``` + +## Anatomy + +| File | Purpose | +|---|---| +| `bridge.json` | Required manifest. Declares name, version, spawn config, verb prefixes. | +| `BRIDGE_VERSION` | Convenience version line (kept in sync with `bridge.json`'s `version`). | +| `server.py` | The bridge runtime. Spawned by Adom Desktop on first verb call. | + +## Why pick Python over Rust for your bridge + +- **Vendor has Python bindings.** KiCad's `pcbnew`, Autodesk Fusion 360's add-in API, MATLAB Engine, NI-VISA, etc. all have first-class Python. +- **No build step.** Edit `server.py`, restart the bridge, done. Zero compile latency during development. +- **Shorter for I/O-bound work.** Spawning subprocesses, parsing files, talking to HTTP services — Python's stdlib gets you there in fewer lines. + +## Why pick Rust over Python (see hello-rust) + +- **Single static binary.** No Python install on the user's machine, no version conflicts, no `pip install` step. The bridge is one self-contained `.exe`. +- **CPU-bound work.** Heavy parsing, image processing, encoding/decoding — Rust is dramatically faster. +- **Static typing + strict error handling.** Catches a class of bugs at compile time that Python only hits at runtime. + +## What's NOT here (intentionally) + +- No `node_modules` / `__pycache__` — keep your bridge zip small. +- No vendor-specific dependencies — `server.py` uses stdlib only so it runs on any Python 3.8+. +- No platform-specific code — the same bridge runs on Windows, macOS, Linux. + +For a real bridge (e.g. one that drives Altium Designer), you'd add: +- Vendor SDK imports / COM/AppleScript calls in `server.py` +- Handler modules in `handlers/` subdirectory (see `plugins/kicad/handlers/` for the pattern) +- A `requirements.txt` if you need third-party deps (Adom Desktop runs `pip install` on first launch — see the SDK guide for the lifecycle) +- If your bridge calls AD back (the loopback direct API), FORWARD the `X-Adom-Caller-Thread`/`-Container`/`-Reason` headers it received and add `X-Adom-Caller-Delegate: hello-python`, so the delegation chain survives (BRIDGE_SDK.md "Caller provenance"). This sample only reads + logs them; it never calls AD back. +- A skills pkg (USER docs) published separately from the runtime zip — the two-artifact layout in the SDK. This sample ships runtime-only. + +## Shipping a new version + +```bash +# 1. Bump BRIDGE_VERSION + bridge.json's "version" field +# 2. Package + upload to wiki +bash scripts/release-bridge.sh hello-python + +# 3. Tell installed clients to refresh +adom-desktop refresh_bridges +``` + +That's the entire ship cycle — no Adom Desktop installer rebuild, no CLI rebuild, no GUI restart.