Skip to content

Rust SDK: in-process mesh node from cargo (design + trial) - #690

Closed
michaelneale wants to merge 19 commits into
mainfrom
micn/native-sdk-cargo-publish
Closed

Rust SDK: in-process mesh node from cargo (design + trial)#690
michaelneale wants to merge 19 commits into
mainfrom
micn/native-sdk-cargo-publish

Conversation

@michaelneale

@michaelneale michaelneale commented May 26, 2026

Copy link
Copy Markdown
Collaborator

What this PR does

Designs and proves the path for a Rust app to depend on mesh-llm as a normal cargo dep and run a real in-process mesh node — the same outcome Swift apps get from .binaryTarget and Kotlin apps get from the AAR.

The shape: a Rust consumer depends on mesh-llm-api-server + mesh-llm-host-runtime as normal Rust source crates and calls the public Rust API directly (MeshNode::builder(), OwnerKeypair::generate(), create_auto_node(...)). skippy-ffi's build.rs fetches the prebuilt patched-llama.cpp static archives from a GitHub release tarball at consumer build time. No FFI wrappers in consumer code, no CMake on the consumer's machine, no separate mesh-llm daemon, no dylib to bundle.

Full design and the alternatives considered in docs/design/RUST_NATIVE_SDK.md.

Status

Draft. Design proposal with a working trial on this branch. Not ready to merge — there are three publish-side tasks still outstanding (see "Not done yet" in the design doc). Open to get sign-off on the design before doing the release-pipeline work.

What's verified working on this branch

  • crates/skippy-ffi/build.rs has a new additive code path: when SKIPPY_LLAMA_TARBALL_URL is set, it fetches the tarball, verifies sha256, extracts into a per-user cache, and points its existing link logic at the extracted archives. With the env var unset, behavior is identical to today.

  • examples/rust-sdk-trial/ lives outside the workspace (declares its own [workspace] table) and depends on mesh-llm crates the way an external app would. Builds with a file:// tarball URL pointing at a locally-packaged 5 MB tarball of the patched-llama.cpp static archives.

  • Run against the live public mesh, it does the equivalent of mesh-llm client --auto:

    rust-sdk-trial: starting
    rust-sdk-trial: owner keypair generated (first 16 hex = dfd6f05df6aaf5bf)
    rust-sdk-trial: discovering and joining a public mesh...
    rust-sdk-trial: selected mesh = (unnamed) (nodes=5, vram=880.4 GB, region=None)
    rust-sdk-trial: mesh serving models = ["unsloth/MiniMax-M2.5-GGUF:Q4_K_M", "unsloth/Qwen3-8B-GGUF@main:Q4_K_M", "unsloth/Qwen3.5-9B-GGUF:Q4_K_M"]
    rust-sdk-trial: starting in-process node...
    rust-sdk-trial: node started
    rust-sdk-trial: node stopped
    

    Real public-mesh discovery via Nostr, real node start/stop, real Rust API surface — no FFI in consumer code.

  • Final binary is 1.7 MB, dynamically linked only to macOS system frameworks. Patched llama.cpp + skippy + mesh-llm host runtime all statically inside.

What's not done

Three things to make this consumable from crates.io (vs path):

  1. Fix the pure-Rust publish chain. Tracked separately in Release crates.io publish chain breaks on HTTP 429 (new-crate rate limit) #691.
  2. Publish mesh-llm-host-runtime, skippy-ffi, skippy-runtime, skippy-server, and other transitively-required crates to crates.io. All pure Rust source; skippy-ffi is self-sufficient via the URL-fetch path on this branch.
  3. Release pipeline produces and uploads llama-stage-<triple>-<flavor>.tar.gz per matrix cell. Each build_* job already runs scripts/build-llama.sh and produces the archives; add a tar + sha256 + upload-artifact step. Naming must match what skippy-ffi/build.rs constructs by default.

Reproduce locally

See examples/rust-sdk-trial/README.md for full instructions.

Out of scope

  • The three publish-side tasks above (separate follow-up work).
  • Tauri-side bundling. Not needed; consumer binary is fully self-contained.
  • An FFI / UniFFI surface for Rust. Not needed; Rust calls Rust directly.

…t build time

Adds crates/mesh-llm-native-sdk: a small Rust crate whose build.rs downloads
the platform/backend-matching libmeshllm_ffi.a from a GitHub release tarball,
verifies sha256, extracts it, and emits link directives.

Mirrors the shape SwiftPM .binaryTarget gives Swift apps today: prebuilt
static archive fetched at build time, static-linked into the consumer's
final binary. No dylib to bundle, no native build on the consumer's
machine.

Backend selection via cargo features (metal, cpu, cuda, rocm, vulkan).
Default URL is a GitHub release URL constructed from CARGO_PKG_VERSION;
override via MESH_LLM_NATIVE_TARBALL_URL for local trials and offline
builds.

Verified end-to-end with a trivial consumer outside the workspace
linking against a locally-packaged static archive.

Design doc: docs/design/RUST_NATIVE_SDK.md.
Rewrite docs/design/RUST_NATIVE_SDK.md to describe what's actually
committed:

- model is build.rs fetches a static archive from a GitHub release URL,
  same shape as Swift's .binaryTarget; no native bytes inside the
  .crate payload
- consumer binary is one self-contained executable, no .dylib to bundle
- artifact is libmeshllm_ffi.a (static archive), not a dylib
- explicit override env vars: MESH_LLM_NATIVE_TARBALL_URL,
  MESH_LLM_NATIVE_TARBALL_SHA256, MESH_LLM_NATIVE_CACHE_DIR
- status section lists what works on this branch (trial verified) and
  what's not yet wired (release pipeline asset, mesh-llm-api-server
  feature, publish-chain 429 fix)
- includes the trial commands and the otool -L proof of static linking

Drops the prior phases that assumed a binary-in-crate model and
crates.io size limit negotiation.
Adds crates/mesh-llm-native-sdk/src/ffi.rs with hand-written Rust
wrappers over the UniFFI C ABI symbols exported by the static archive:

- RustBuffer / RustCallStatus / ForeignBytes mirror types
- rustbuffer_free helper for safely consuming UniFFI string returns
- generate_owner_keypair_hex() as the first real wrapper

UniFFI 0.31 does not ship a Rust bindings generator (only Swift,
Kotlin, Python, Ruby), so wrappers are written by hand to keep the
single-shared-static-archive model (one artifact for Swift, Kotlin,
Node, and Rust). Module is mechanical and small; the design doc calls
out the maintenance trade-off vs publishing a Rust-native source crate
graph to crates.io.

Verified end-to-end: a faux consumer outside the workspace calls
mesh_llm_native_sdk::generate_owner_keypair_hex() and gets back fresh
128-character hex keypairs (different bytes each call), proving real
mesh-llm code inside the static archive is reachable and runs.
Adds an additive code path in skippy-ffi/build.rs: when
SKIPPY_LLAMA_TARBALL_URL is set, download the tarball, verify sha256
against the .sha256 sidecar (or SKIPPY_LLAMA_TARBALL_SHA256), extract
into a per-user cache, and set SKIPPY_LLAMA_BUILD_DIR to the extracted
root. The rest of the build script proceeds as if the consumer had run
'just llama-build' themselves.

This unlocks the Option B Rust SDK story: consumers depend on
mesh-llm-api-server + mesh-llm-host-runtime as normal Rust source
crates, and skippy-ffi fetches the prebuilt llama.cpp/skippy static
archives at consumer build time. No FFI wrappers on the consumer
side; the public Rust API (MeshNode::builder(), MeshClient, etc.) is
called directly.

Workspace-internal builds are unaffected (env var unset -> original
behavior using .deps/llama-build).

Override env vars:
- SKIPPY_LLAMA_TARBALL_URL: file:// or https:// URL
- SKIPPY_LLAMA_TARBALL_SHA256: expected hex; otherwise fetched from
  <url>.sha256 sibling
- SKIPPY_LLAMA_CACHE_DIR: cache root (default ~/.cache/skippy-llama-stage)
- SKIPPY_LLAMA_TARBALL_FLAVOR: cpu|metal|cuda|... (default inferred
  from target triple)

Verified end-to-end: a Rust app outside the workspace
(/tmp/sprout-faux2) depends on mesh-llm-api-server + mesh-llm-host-runtime
by path, builds with SKIPPY_LLAMA_TARBALL_URL pointing at a 5 MB
locally-packaged tarball, links successfully, runs
mesh_llm_api_server::OwnerKeypair::generate() and produces different
real ed25519 keypairs on each run.
Drops the mesh-llm-native-sdk crate (Option A, FFI wrappers over UniFFI
ABI). The earlier trial proved it works, but Option B — pure Rust source
crates on crates.io with skippy-ffi fetching prebuilt llama.cpp static
archives from a release tarball — is the better fit:

- No FFI wrappers in consumer code; consumers call the public Rust API
  (MeshNode::builder(), OwnerKeypair, etc.) directly.
- 5 MB tarball per platform/backend (just patched llama.cpp .a files)
  instead of 131 MB (full libmeshllm_ffi.a).
- No ongoing hand-written wrapper maintenance as the SDK surface grows.
- Existing skippy-ffi link logic (search dirs, link directives) reused
  unchanged.

Rewrites docs/design/RUST_NATIVE_SDK.md to describe Option B as the
chosen path, with the local trial reproduction commands, the three
remaining publish-side tasks, and explicit caveats.
A working end-to-end consumer that exercises the design proposed in
docs/design/RUST_NATIVE_SDK.md:

- declares its own [workspace] table so it depends on mesh-llm crates
  the way an external app would
- generates an owner keypair via OwnerKeypair::generate()
- runs the equivalent of 'mesh-llm client --auto' through
  create_auto_node(owner, PublicMeshQuery::default())
- starts the in-process node, lists the models the mesh exposes,
  cleanly stops

Verified locally against the live public mesh: discovers a 5-node mesh
serving real models (MiniMax-M2.5, Qwen3-8B, Qwen3.5-9B), starts the
node, prints the selected mesh, stops cleanly.

Build instructions in examples/rust-sdk-trial/README.md. Requires
SKIPPY_LLAMA_TARBALL_URL pointing at a locally-packaged tarball of the
patched-llama.cpp static archives (file:// for now; same shape will
work with the release-asset URL once the release pipeline ships those
tarballs).
Follow-on to docs/design/RUST_NATIVE_SDK.md. Investigates what it would
take for the mesh-llm shipped binary to consume mesh-llm-api-server
the same way an external Rust app does, instead of reaching into
host-runtime internals.

Findings:

- The user-facing CLI subcommands (discover, download, models,
  blackboard) already have direct SDK equivalents. The duplication
  is roughly 400 lines of host-runtime-internal access in
  crates/mesh-llm-host-runtime/src/cli/commands/*.
- Three change groups: (1) domain commands route through SDK, (2)
  serve/client route through run_serve(MeshServeSpec) from PR #641,
  (3) auth either moves into the SDK or is explicitly marked
  binary-only.
- Concrete cost: 400-1000 lines re-pointed at SDK calls, plus the
  auth decision. Not a 7K-line rewrite. CLI shell (clap parsing,
  output, TUI) stays as the binary's job.
- Several CLI surfaces explicitly stay bespoke: update, model-prepare,
  benchmark, gpu enumerate, stop, http-to-management-api commands.

Sequencing depends on landing #690, the gated-relay split, and #691
first. Without mesh-llm-api-server actually on crates.io, the
'binary uses the SDK' story is internal-only.
First mechanical step of the 'CLI on top of SDK' design in
docs/design/CLI_ON_TOP_OF_SDK.md.

cli::commands::discover::run_nostr_discover previously called
crate::network::nostr::discover(...) directly. It now goes through
mesh_llm_api_server::discover_public_meshes(PublicMeshQuery { ... }) -
the same surface external Rust consumers (and examples/rust-sdk-trial/)
use.

A small local lift_public_mesh helper converts each PublicMesh back
into the host-runtime DiscoveredMesh shape so the existing CLI
display, scoring (nostr::score_mesh), and Display impl stay untouched.
No UX change.

Verified against the live public mesh: 'mesh-llm discover',
'mesh-llm discover --name <name>', and 'mesh-llm discover --min-vram N'
all produce identical output to before.

Docs (docs/design/CLI_ON_TOP_OF_SDK.md) updated to reflect what was
achievable in Change 1 and what's blocked on SDK extensions:

- download is blocked on the SDK's MeshModels::download lacking a
  progress callback. Switching today would silently lose the
  CLI's terminal progress bar.
- The 'models' subcommand uses a lot of host-runtime-internal model
  helpers (layered packages, capability introspection, usage records,
  catalog/HF search variants) that have no SDK equivalent and
  shouldn't grow on speculation.
No behaviour change. Just brings the file into compliance with
'cargo fmt --check' after the new fetch_and_extract_llama_stage code.
Every workspace-internal path-dep that was missing a version specifier
now carries both:

    foo = { version = "0.66.0", path = "../foo" }

This is the prerequisite for those crates to be consumable from
crates.io once they're published: cargo resolves path-deps from the
local checkout, but external consumers pulling from the registry need
a version constraint. Without this, the workspace builds fine
internally but an external 'cargo add mesh-llm-api-server' fails to
resolve transitively.

Workspace-internal dep versions match each target crate's own declared
version (almost all are 0.66.0; mesh-mixture-of-agents is 0.1.0).

68 lines patched across 18 crate manifests. The workspace and the
examples/rust-sdk-trial consumer both still build cleanly. A
cargo publish --dry-run on the new chain walks every crate without
errors (some are correctly skipped because their predecessors aren't
on crates.io yet, but the manifests themselves are publishable).
scripts/publish-crates.sh now publishes the full set of crates needed
for an external Rust consumer to depend on mesh-llm-api-server with
the host-runtime feature:

- 18 new crate names added in topological order, interleaved with the
  existing 11. The list now covers mesh-llm-host-runtime, the
  skippy-* family, mesh-llm-system, openai-frontend, mesh-mixture-of-agents,
  mesh-llm-ui, mesh-llm-gpu-bench, model-{package,resolver},
  mesh-llm-{guardrails,plugin,identity,protocol,routing,types}.
- unpublished_registry_deps() now reads each crate's own Cargo.toml
  rather than carrying a hard-coded dep table, so it stays in sync as
  the dep graph evolves. Handles the dir-name vs crate-name mismatch
  for mesh-client/ -> mesh-llm-client.
- crate_needs_no_verify() marks the native-linking crates
  (skippy-ffi/runtime/server/cache/coordinator/topology/protocol/metrics,
  mesh-llm-system, mesh-llm-host-runtime, mesh-llm-node,
  model-package, model-resolver) for --no-verify, because the
  packaged tarball's build.rs cannot find .deps/llama-build from
  inside target/package/. The release pipeline's existing pre-publish
  cargo build is the real gate.

Validated by 'bash scripts/publish-crates.sh --dry-run --allow-dirty'
walking the full chain cleanly: 15 crates fully verify and 14 are
correctly skipped with 'depends on X@0.66.0 not yet on crates.io'
messages that resolve once each predecessor lands.

docs/design/RUST_NATIVE_SDK.md updated:
- Item 2 (publish chain expansion) moved from 'not done' to 'done on
  this branch'.
- Item 1 (HTTP 429 / issue #691) is now even more important because
  the chain grew by 18 new crate names, ~3x the new-crate-name volume
  of v0.66.0.
Each Linux/macOS build_* job in the release workflow now packages the
patched llama.cpp static archives from
.deps/llama-build/build-stage-abi-<backend>/ into a release-asset-shaped
tarball plus sha256 sidecar after the existing cmake build.

This is the third and last piece of plumbing needed for an external
Rust app to consume mesh-llm via cargo:

1. mesh-llm-api-server (and its deps) on crates.io  -- requires #691
   to land first; the chain is otherwise prepared by the prior
   commits on this branch.
2. skippy-ffi's build.rs fetches the prebuilt static archives from a
   URL  -- already on this branch.
3. The release pipeline actually publishes those tarballs  -- this
   commit.

Naming matches skippy-ffi/build.rs's default URL construction:
llama-stage-<target_triple>-<flavor>.tar.gz, with .sha256 sidecar.
Tarballs land in dist/ so they're picked up by the existing
upload-artifact -> publish flow that creates GitHub release assets.

New script scripts/package-llama-stage.sh extracts the shared
packaging logic; verified locally against the same trial that
examples/rust-sdk-trial/ exercises (5.1 MB metal tarball, consumer
links cleanly, joins the live public mesh).

Wired into the Linux/macOS build_* jobs (build, build_linux_arm64,
build_linux_cuda, build_linux_cuda_blackwell, build_linux_rocm,
build_linux_vulkan). Windows jobs are not wired because they use
PowerShell and the package script is bash; deferred to a follow-up.
Windows Rust consumers can still consume the SDK by overriding
SKIPPY_LLAMA_TARBALL_URL.

docs/design/RUST_NATIVE_SDK.md updated to mark item 3 done for
Linux/macOS and call out the Windows gap honestly.
…-publish

* origin/main:
  fix(lint): many linter corrections (#696)
  Upgrade workspace to Rust 2024 edition
  Fix dispatched Swift release manifest flow
  Fix metadata-only package verification cache
  Fix Blacksmith CI discrepancies
…ime feature

Lets a Rust app drive a real mesh-llm node from the published SDK \u2014 the
same iroh-backed peer the binary runs, not the HTTP-shim client that
MeshNode::start() used previously.

```rust
let node = MeshNode::builder()
    .identity(OwnerKeypair::generate())
    .join(invite)
    .role(MeshRole::Client)
    .relay("https://gated.example/")
    .relay_auth("https://gated.example/", "<bearer-token>")
    .max_vram_gb(0.0)
    .build()?;

node.start().await?;
let invite = node.invite_token().await;
```

Architecture:

- New `mesh_llm_host_runtime::host_node` module exposes `HostNodeSpec`
  + `HostNode` + `start_host_node` as the curated entry point into the
  internal `mesh::Node`. SDK consumers don't see internal types directly.

- `mesh-llm-api-server` gains a `host-runtime` Cargo feature
  (off by default). With it on, depends on `mesh-llm-host-runtime` and
  `MeshNode::start()` calls `host_node::start_host_node` with the
  builder's relay / relay_auth / role / quic_bind / max_vram fields.

- Builder API extended with .role(), .relay(), .relay_auth(),
  .quic_bind(), .max_vram_gb(), .no_enumerate_host(). New types
  `MeshRole` and `MeshQuicBind` mirror the CLI surface; SDK consumers
  never have to import host-runtime-internal types.

- Without the feature, the new builder methods are still callable
  (forward-compat: an SDK consumer can configure relay-auth without
  caring whether the runtime is wired) \u2014 fields are stored but
  ignored, and start() falls back to the existing HTTP-shim behaviour.

- New invite_token() / set_display_name() accessors on MeshNode
  (host-runtime-only) so consumers can introspect / advertise their
  running node.

Cycle fix: `mesh-llm-host-runtime` had an unused declared dep on
`mesh-llm-api-server` (no `use` sites in src/). Dropped to let the
inverse dep land cleanly.

Test: crates/mesh-llm-api-server/tests/host_node_gated_relay.rs
(gated on host-runtime feature) brings up an in-process iroh-relay with
AccessConfig::Restricted, builds a MeshNode with .relay_auth(...) for
the matching token, and asserts node.start() reaches the gated relay
end-to-end. A second test pins that the wrong token is denied with
'not authorized' at the iroh wire layer.
SDK consumers can now launch the full mesh node *including* the OpenAI
HTTP API surface from Rust code, without going through the binary CLI:

```rust
let node = MeshNode::builder()
    .identity(OwnerKeypair::generate())
    .join(invite)
    .role(MeshRole::Client)
    .relay("https://gated.example/")
    .relay_auth("https://gated.example/", "<bearer>")
    .openai_port(0) // 0 = OS-assigned ephemeral port
    .build()?;

node.start().await?;
let base = node.openai_base_url().await.unwrap();
// e.g. http://127.0.0.1:54321
// Hit /v1/chat/completions, /v1/models, /v1/responses there as usual.
```

Mechanism:

- New `mesh_llm_host_runtime::host_node::start_openai_proxy(node, port,
  listen_all)` wraps the internal `network::openai::ingress::api_proxy`
  with default empty target_rx (routing pulls remote peers dynamically
  from `node.hosts_for_model()` at request time) and a background drain
  for runtime-control messages (SDK consumers without local serving
  have no one to handle Load/Unload control requests).

- `MeshNodeBuilder` gains `.openai_port(port)` and
  `.openai_listen_all(bool)` setters. With the `host-runtime` feature on
  and `openai_port` set, `MeshNode::start()` binds and spawns the proxy
  alongside the mesh node; `MeshNode::stop()` aborts it.

- New `MeshNode::openai_base_url()` accessor returns the bound URL
  after start (Some when the proxy is running, None otherwise).

End-to-end test `openai_proxy_binds_and_serves_v1_models_over_http`:
constructs a MeshNode via the SDK with .openai_port(0), GETs /v1/models
over real TCP, asserts 200 OK with a JSON body containing the `data`
field (OpenAI shape), then stops the node and asserts the port no
longer answers.

Scope clarification in host_node module docs: the "this does not do"
list shrinks; OpenAI proxy is no longer in it. Local model serving
still requires plugging an EmbeddedServingController, which is a
separate concern (client-only embedders don't need it because the
proxy routes to remote mesh peers).
Adds the missing piece: SDK consumers can now run *exactly* what the
mesh-llm binary runs \u2014 not a degraded subset. `run_serve(spec)`
constructs argv from a typed `MeshServeSpec` and feeds it to the same
`runtime::run_with_args` entry point the binary calls.

```rust
use mesh_llm_api_server::{run_serve, MeshServeSpec};

run_serve(MeshServeSpec {
    client: true,
    auto: true,
    relays: vec!["https://gated.example/".into()],
    relay_auths: [(
        "https://gated.example/".to_string(),
        "<bearer>".to_string(),
    )].into_iter().collect(),
    port: Some(9337),
    console_port: Some(3131),
    max_vram_gb: Some(0.0),
    ..Default::default()
}).await?;
```

That gets the full thing: auto-discovery, election, tunnel manager,
OpenAI proxy, management console, local model serving (when configured),
plugin host. Same code path as `mesh-llm serve` / `mesh-llm client`.

Mechanism:

- `runtime::run()` split into a thin env-driven entry and a new
  `run_with_args(argv)` that takes a caller-supplied argv. Binary
  unchanged \u2014 main() still calls run() which forwards std::env::args_os.

- `mesh_llm_host_runtime::run_with_args(argv)` re-exports it at the
  crate root.

- `host_node::MeshServeSpec` covers the realistic CLI surface: client,
  auto, publish, mesh_name, region, display_name, join, discover,
  models, ggufs, mmproj, port, console_port, headless, blackboard,
  relays, relay_auths, nostr_relays, bind_port, bind_ip, listen_all,
  max_vram_gb, no_enumerate_host, config, owner_key, owner_required,
  node_label, trust_owners, debug. Plus an extra_args escape hatch.

- `host_node::run_serve(spec)` serialises the spec to argv via
  `MeshServeSpec::into_argv()` and calls `run_with_args`.

- `mesh-llm-api-server::{run_serve, MeshServeSpec}` re-exports them
  through the published SDK crate (gated on the host-runtime feature).

Regression-catcher test `mesh_serve_spec_argv_parses_via_the_real_cli_parser`:
constructs a fully-populated MeshServeSpec, calls into_argv(), runs it
through `normalize_runtime_surface_args` + `Cli::try_parse_from` (the
real parser the binary uses), asserts every field round-trips. If a
future refactor renames a CLI flag, this fails immediately and points
at the drifted MeshServeSpec field.

This is what sprout (or any Rust app) actually needs to run a full
mesh-llm node from inside its own process. The earlier
`MeshNodeBuilder` + `start_openai_proxy` work remains useful for
finer-grained client-only embedders that don't want the whole runtime
machinery, but `run_serve` is the answer to 'I want my Rust app to do
exactly what `mesh-llm serve` does.'
Adds the missing 'how do I run mesh-llm from Rust?' answer in three
places so it's discoverable however a consumer arrives:

- `docs/SDK.md` gains a 'Run the full mesh-llm runtime from Rust
  (host-runtime feature)' section under Rust Usage. Explains the
  feature flag, contrasts with MeshNodeBuilder (fine-grained vs
  full-runtime), gives a complete relay-auth + OpenAI + console
  example, lists every MeshServeSpec field.

- `crates/mesh-llm-api-server/README.md` gets a parallel section so
  consumers landing on the crate page (e.g. via docs.rs or crates.io)
  see the run_serve story without leaving the crate docs.

- The `pub use` re-export of `run_serve` / `MeshServeSpec` in
  `mesh-llm-api-server/src/lib.rs` now carries a full rustdoc example
  with the same MeshServeSpec, so `cargo doc` surfaces it
  prominently.

No code changes; documentation only.
cargo fmt under edition 2024 sorts uppercase types alongside lowercase
modules. Reorders imports in the SDK files cherry-picked from #641.
No logic change.
Three small cleanups to make this branch green on a workspace that
doesn't (yet) have the rest of #641's gated-relay polish:

1. skippy-ffi/build.rs: collapse the nested ifs in the tarball-URL
   fetch path into a single let-chain so clippy's collapsible-if
   doesn't fire.

2. crates/mesh-llm-host-runtime/src/host_node.rs: remove three tests
   that depend on helpers only present on the gated-relay PR
   (id_returns_bare_hex_endpoint_id needs the bare-hex HostNode::id()
   refactor; shutdown_closes_the_mesh_endpoint needs
   Node::endpoint_is_closed_for_tests; shutdown_releases_fixed_quic_bind
   depends on the shutdown polish that releases the QUIC bind cleanly).
   They come back once that work is on main. Also remove the
   helpers (free_local_udp_port, probe_quic_port_released) those
   tests pulled in.

3. The mesh_serve_spec_argv_parses_via_the_real_cli_parser test no
   longer asserts on cli.relay_auth (that field doesn't exist on this
   branch). Updated to use 'https://public.example/' instead of
   'https://gated.example/' since gated-relay support isn't here yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant