← Commit history

Modernize sample: 3 verbs, v1.3.0, ADOM_BIND_HOST, caller headers, _reportIssues, --ai-thread install (wiki #229)

John Lauer ·101f5a1d20 ·3mo ago ·parent 1859af1
1 file changed +81−124
README.md+81−124
@@ -1,124 +1,81 @@-# Adom Desktop - Hello Sample Bridge (Python)--![How the hello-python bridge works](arch.png)--![hello-python verbs Claude can call](verbs.png)--![What you can ask Claude to do](outcomes.png)--## 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\ No newline at end of file+# 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.