app
DEPRECATED: Bridge SDK (moved into Adom Bridge)
Public Made by Adomby adom
Bridge SDK guide: bridge.json schema, kind:python/node/exe, hello-python + hello-rust reference templates, packaging + lifecycle commands.
← Commit history
SDK v1.9.47: corrected bridge.json schema (entrypoint/kind) + cold-start tiers section
3 files changed
+57−11
SKILL.md+55−9@@ -33,28 +33,45 @@ If a *bridge verb* misbehaves → fix the bridge. If a *generic AD capability* i ```jsonc { - "name": "blender", // registry name → verb prefix "blender_" + "manifest_version": 1, + "name": "blender", // registry name → verb prefix "blender_" + "displayName": "Blender", // in-app chip label (the tool's real name) "version": "1.2.0", // numeric; a newer CACHE copy supersedes the bundled seed "description": "Drive Blender headless + GUI", "author": "you", - "docs": "https://wiki.adom.inc/adom/adom-desktop-blender-bridge", // your OWN dedicated page (drives skillPkg + hero) + "license": "MIT", + "docs": "https://wiki.adom.inc/adom/adom-desktop-blender-bridge", // your OWN page (drives skillPkg + hero) "hero": "https://.../hero.png", // optional; else AD uses your wiki page hero, else a monogram "spawn": { - "kind": "process", // "process" (AD spawns it) | "external-http" (AD only probes) - "cmd": "python", // or a bundled interpreter (e.g. ship node_modules; see Prewarm) - "args": ["server.py", "--port", "{port}"], // {port} ← AD's STABLE allocated port + "kind": "python", // python | node | exe | external-http (NOT "process") + "entrypoint": "server.py", // the file/exe AD launches; AD AUTO-APPENDS `--port <port>` to argv + "port": 0, // 0 = AD picks a STABLE port (recommended). Bind 127.0.0.1:<that port>. "persistent": true, // AD's supervisor respawns it if it dies - "cwd": "." + "healthEndpoint": "/health", // INSIDE spawn. AD probes it for the chip (default /health) + "stopMethod": "kill", // kill | sigterm | graceful_endpoint + "killImageName": "python.exe" // image name for taskkill on stop (kind:python/node) }, - "healthEndpoint": "/health", // default /health; AD probes it for the chip + "verbPrefixes": ["blender_"], // any verb with these prefixes routes to you + "verbs": ["blender_render", "blender_status", "blender_describe"], // every verb (routing + Verbs tab) "statusVerb": "blender_status", // verb a caller polls after a long op times out - "updateManifestUrl": "https://wiki.adom.inc/api/v1/pages/adom-desktop-blender-bridge/files/blender-manifest.json" + "updateManifestUrl": "https://wiki.adom.inc/api/v1/pages/adom-desktop-blender-bridge/files/blender-manifest.json", + + // v1.9.47 cold-start (see "Cold-start tiers" below): + "detect": { // Tier 2 — how AD DETECTS your HOST APP. AD NEVER installs it. + "hostApp": "Blender", // omit the whole `detect` block if your bridge brings its own runtime + "appPathsExe": "blender.exe", // (e.g. pup ships its own browser → no host app) + "paths": { "windows": ["%ProgramFiles%\\Blender Foundation\\*\\blender.exe"] } + }, + "prewarm": { "assets": [] } // Tier 1 — heavy runtime assets AD prewarms (e.g. ["chrome-for-testing"]) } ``` -- **`{port}`** — AD allocates a STABLE port (persisted across respawns + AD restarts) and substitutes it. Bind `127.0.0.1:{port}`. NEVER hardcode a port (Hyper-V/Docker silently reserve ranges — see PORTS.md). +- **`spawn.kind`** is `python` | `node` | `exe` | `external-http` — there is **no `"process"` kind**, and no `cmd`/`args`/`cwd`. AD launches `spawn.entrypoint` and **automatically appends `--port <port>`** to its argv; your server parses `--port`. (`external-http` = AD doesn't spawn, only probes a port you declare via a `discovery` block.) +- **`spawn.port: 0`** → AD allocates a STABLE port (persisted across respawns + AD restarts) and passes it. Bind `127.0.0.1:<port>`. NEVER hardcode a port (Hyper-V/Docker silently reserve ranges — see PORTS.md). +- **`spawn.healthEndpoint`** lives **inside `spawn`** (not at the top level), default `/health`. - **`updateManifestUrl`** — the full URL of YOUR manifest on YOUR page. **Declare it in `bridge.json`** so it survives a republish; AD polls it (on launch + every 4h) and auto-updates users. (AD also remembers the install URL in `~/.adom/bridge-install-urls.json` as a fallback, but the declared field is the durable, author-intended path.) - **`docs`** — point at YOUR dedicated wiki page. AD derives your **skillPkg** (`adom/<slug>`) and your card hero from this. Don't point it at a shared/structural page. +- **`detect` / `prewarm`** — the v1.9.47 cold-start declarations (full rules in "Cold-start tiers" below). `detect` = your HOST APP (AD detects, never installs); `prewarm` = your heavy RUNTIME assets (AD prewarms/auto-installs). A node bridge that ships its deps still works without `prewarm`; declare `prewarm.assets` only for big *downloaded* assets like a browser. --- @@ -149,6 +166,35 @@ A cold first call that pays multi-minute setup (npm install, downloading a runti --- +## Cold-start tiers, host-app detection & the `bridge_readiness` probe (v1.9.47) + +A bridge has TWO kinds of dependency, and **AD treats them OPPOSITELY.** Get this right or a first-install probe (e.g. HD's "what tools do I have") triggers a slow install at the worst moment. + +**Tier 1 — your RUNTIME (Node, Python, your own browser download): AD prewarms + auto-installs it.** This is your plumbing. On first boot AD installs Node/Python in the background (winget) and prewarms heavy assets you declare. You may also download your own runtime asset (pup downloads Chrome-for-Testing) — fine, it's yours. **But do it in the BACKGROUND: a `*_status` / `*_readiness` / ANY probe verb must NEVER block on a heavy download.** Spawn your server fast (it usually doesn't need the asset to *start*), kick the download off detached, and report `state:"warming"` until ready. A synchronous-download-on-first-verb is the exact footgun this release fixed (pup's 150 MB Chrome fetch used to block the probe). + +**Tier 2 — the HOST APP (KiCad, Fusion, Altium, …): AD ONLY DETECTS it — NEVER installs it.** The user's app is theirs; installing it pre-emptively is rude. Its *presence* is the signal: a machine with KiCad belongs to a KiCad user (EDA users are mono-tool — a Fusion user isn't a KiCad user). So AD detects it and **won't even prewarm your bridge if your host app isn't installed** (no point spinning up the KiCad bridge on a no-KiCad machine; on-demand spawn still works if they install it later). + +**Declare both in `bridge.json`:** +```json +"detect": { // Tier 2 — how AD finds your HOST APP (detection only) + "hostApp": "KiCad", + "appPathsExe": "kicad.exe", // optional: Windows App Paths registry lookup (most reliable) + "paths": { // optional: candidate paths, %VAR% expanded, one * = a version dir + "windows": ["%ProgramFiles%\\KiCad\\*\\bin\\kicad.exe"], + "macos": ["/Applications/KiCad/KiCad.app"], + "linux": ["/usr/bin/kicad"] + } +}, +"prewarm": { "assets": ["chrome-for-testing"] } // Tier 1 — heavy runtime assets AD prewarms + reports +``` +A bridge that brings its OWN runtime (pup ships its own browser) **omits `detect`** — it has no external host app. AD infers the runtime from `spawn.kind` (node→Node, python→Python). + +**The read-only probe: `bridge_readiness`.** AD aggregates all of this into ONE side-effect-free verb the setup AI calls — it **never spawns a bridge, never installs/downloads**. Per bridge: `{hostApp, hostAppInstalled, runtime, runtimeReady, assets, state}` where `state` ∈ **`ready`** (use it) | **`warming`** (runtime ok, a heavy asset still downloading in the background — re-poll, don't trigger it) | **`needs-runtime`** (node/python installing) | **`no-app`** (host app not installed → not relevant here). Plus a top-level `edaToolsInstalled` list — the one-line answer to "what EDA tools do I have." **Tell your users (in your skill): for a "what do I have / is it ready" question call `bridge_readiness`, NOT your `*_status` verb** — a `*_status` may spawn your bridge; readiness never does. + +Your two own cold-start verbs (above) still apply: `<prefix>_readiness` (read-only `{ready, installing, installProgressPct, lastError}`) + `<prefix>_prewarm` (`{wait}`-able). Those drive YOUR bridge specifically; `bridge_readiness` is the AD-level aggregate that detects + summarizes across all bridges without spawning any. + +--- + ## The SKILL SET you should ship (not one SKILL.md — a small library) Don't cram everything into one file. Ship **three kinds** of skill, each with a different reader:
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-desktop-bridges", - "version": "1.1.0", + "version": "1.1.1", "type": "app", "description": "Bridge SDK: build/publish/discover an adom-desktop bridge. Root skill = the full SDK guide; sub-skills = shipping-a-bridge, bridge-author (authoring walkthrough), and 3 fill-in-the-blanks templates (dev/publish/user). bridge.json schema, lifecycle verbs, rich-hints-in-output rule.", "dependencies": {},
page.json+1−1@@ -4,7 +4,7 @@ "slug": "adom-desktop-bridges", "title": "Adom Desktop - Bridge SDK", "brief": "Bridge SDK guide: bridge.json schema, kind:python/node/exe, hello-python + hello-rust reference templates, packaging + lifecycle commands.", - "version": "1.1.0", + "version": "1.1.1", "tags": [], "license": "MIT", "discovery_triggers": [