feat(mesh): download-on-demand mesh node + membership-gated admission#1586
Draft
michaelneale wants to merge 5 commits into
Draft
feat(mesh): download-on-demand mesh node + membership-gated admission#1586michaelneale wants to merge 5 commits into
michaelneale wants to merge 5 commits into
Conversation
…esh preset - Bump mesh-llm pin ebc3ab4c -> 49cf0342 (113 commits: server-side tool-call emulation for models without native tool support, reasoning format fixes, iroh 1.0 stable, and more) - Adapt to initialize_host_runtime() becoming async upstream - mesh_agent_preset now takes an optional runtimeId: "goose" emits goose's env dialect (GOOSE_PROVIDER=openai, OPENAI_HOST without /v1, GOOSE_MODEL) with no sidecar MCP, so goose — including the bundled goose-acp sidecar — can run inference on the relay mesh. Default and unknown ids preserve the buzz-agent behavior.
The mesh-llm feature previously statically linked the whole mesh node (~52 MB binary weight, +17.5 MB compressed) which kept it off by default behind 'just mesh=1' builds. Replace the in-process embedding with the pattern Buzz already uses for every other capability binary: - mesh_llm/node_install.rs: first use downloads the official pinned mesh-llm release (~30 MB), verifies the published sha256, extracts to a versioned cache dir, and emits progress app events for the UI. - mesh_llm/node_process.rs: spawns 'mesh-llm serve/client --headless' as a supervised child process (own process group, SIGTERM-then-kill teardown) and drives it over its local management API — the same HTTP surface the SDK's embedded handle used internally. - DesktopMeshRuntime keeps its exact API; dial_endpoint_addr respawns with the extra --join token (the standalone node has no join-at- runtime endpoint yet; upstream candidate: POST /api/join). - mesh_node_install_status command so the UI can say 'first start will download the mesh runtime' up front. - mesh-llm-sdk/host-runtime git deps removed entirely; the mesh-llm cargo feature is now a few KB of client code (57.9 MB binary with the feature on vs 57.3 without — was 109.7 MB). Admission/coordination is unchanged and mesh-native: nostr discovery, invite-token admission, iroh transport — private by default (no --publish), same flags as the embedded config used. Ignored e2e test covers the full first-use flow (download, checksum, cache hit, spawn, status + attestation verification, /v1/models, stop): cargo test --features mesh-llm -- --ignored mesh_node_e2e
Buzz decides membership; mesh enforces it — the idiomatic split: - Every Buzz-managed node gets an auto-initialized mesh owner identity (mesh-llm auth init, cached at mesh-node/owner.key) and runs with --owner-key --owner-required --trust-policy allowlist. - The relay's kind:30621 sanitizer now carries the reporter's VERIFIED owner id (unverified claims are dropped), so the membership-gated status pipeline doubles as the trust-allowlist distribution channel. - Desktops build --trust-owner lists from those events at node start (trusted_owner_ids_from_events); own owner id always included. - Invite tokens remain dial metadata only. Proven by an ignored 3-node e2e (mesh_trust_allowlist_admits_member_rejects_stranger): a peer with an allowlisted owner is admitted; a stranger holding the SAME valid invite token never enters the peer table. - mesh-llm added to KNOWN_AGENT_BINARIES and the node stamped with BUZZ_MANAGED_AGENT, so the orphan sweep reclaims crash leftovers without touching user-run standalone mesh-llm processes. - Public iroh relays stay disabled (v1 posture): reachability continues to flow through the relay's membership-validated call-me-now pairing.
…e.rs The desktop no longer links mesh native code (the node is a downloaded release binary), so the mesh-llm rev resolution + llama.cpp Metal prebuild + cache steps in ci.yml/release.yml are dead weight — and were failing at the new mesh rev. The Tauri release build keeps --features mesh-llm, which is now a few KB of client code. Also split KNOWN_AGENT_BINARIES + name matchers into managed_agents/known_binaries.rs — runtime.rs was at its file-size budget and the mesh-llm sweep entry pushed it over.
d77ceac to
6eaf404
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replaces the statically-linked mesh-llm node with a download-on-first-use managed sidecar, and adds membership-gated mesh admission enforced by mesh's own ownership/trust layer.
The
mesh-llmcargo feature previously compiled the whole mesh node into buzz-desktop (+52.4 MB binary, +17.5 MB compressed download), which is why it stayed off by default behindjust mesh=1. This PR removes themesh-llm-sdk/mesh-llm-host-runtimegit deps entirely — the feature is now +0.6 MB (57.3 → 57.9 MB) and could plausibly become default-on.--trust-policy allowlistfed from Buzz membershipebc3ab4c(113 commits stale)49cf0342), incl. server-side tool-call emulationHow it works
Download-on-demand (
mesh_llm/node_install.rs): firstmesh_start_nodefetches the pinned official release from GitHub (MESH_NODE_VERSION = v0.72.2), verifies the published.sha256sidecar (checksum fetched before the big download), extracts to a versioned cache dir, and emitsmesh-node-install-progressapp events for the UI. Amesh_node_install_statuscommand lets the UI say "first start downloads the mesh runtime (~30 MB)" up front.Managed process (
mesh_llm/node_process.rs): spawnsmesh-llm serve/client --headlessas a supervised child (own process group, SIGTERM→SIGKILL teardown,kill_on_drop) and drives it over its local management API (/api/status) — the same HTTP surface the SDK's embedded handle used internally. The node is stampedBUZZ_MANAGED_AGENTandmesh-llmjoinsKNOWN_AGENT_BINARIES, so the existing orphan sweep reclaims crash leftovers without ever touching a user-run standalone mesh-llm.Membership-gated admission (
mesh_llm/owner_identity.rs+ relay): Buzz decides membership; mesh enforces it.mesh-llm auth init, cached) and runs--owner-key --owner-required --trust-policy allowlist.--trust-ownerlists from those events at node start.Any-agent mesh inference (
mesh_llm/preset.rs):mesh_agent_presetaccepts an optionalruntimeId;"goose"emits goose's env dialect (GOOSE_PROVIDER=openai,OPENAI_HOST,GOOSE_MODEL, no sidecar MCP) so goose — including the bundledgoose-acpfrom #1526 — can run on mesh inference. Default stays buzz-agent.Verification
mesh_node_e2e_download_spawn_openai_surface(ignored, network): full first-use flow — download, checksum, cache hit, owner identity create/reuse, spawn,/api/status(attestation + ownership verified),/v1/models, stop.mesh_trust_allowlist_admits_member_rejects_stranger(ignored, 3 nodes): a peer with an allowlisted owner is admitted; a stranger holding the same valid invite token never enters the peer table — proving tokens are dial metadata and ownership is the gate.Known gaps / follow-ups
--joinappended (no join-at-runtime management endpoint yet). Upstream candidate:POST /api/joinin mesh-llm.auth statusoutput is text-parsed; upstream candidates:--jsonflag + a light typed management-API crate so schema drift fails at pin-bump compile time instead of runtime.MESH_NODE_VERSIONbump with the ignored E2Es as the re-validation gate.