Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
326 changes: 319 additions & 7 deletions Cargo.lock

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion crates/mesh-llm-api-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,30 @@ categories = ["api-bindings", "network-programming"]
[features]
host-io = ["mesh-llm-api-client/host-io"]

# Run a real iroh-backed mesh node in-process (gossip, relay registration
# including --relay-auth, invite tokens, QUIC peer connections), instead of
# the default HTTP-shim client behaviour. Drags `mesh-llm-host-runtime` and
# its transitive deps (skippy, llama.cpp link path, etc.) into the build,
# so it is off by default. Consumers who want a Rust app to act as a real
# mesh peer should enable it.
host-runtime = ["dep:mesh-llm-host-runtime"]

[dependencies]
anyhow.workspace = true
mesh-llm-api-client = { path = "../mesh-llm-api-client", version = "0.66.0" }
mesh-llm-node = { path = "../mesh-llm-node", version = "0.66.0" }
# Optional, gated by the `host-runtime` feature.
mesh-llm-host-runtime = { path = "../mesh-llm-host-runtime", optional = true, default-features = false }
tokio = { version = "1", features = ["sync"] }

[dev-dependencies]
tokio = { version = "1", features = ["macros", "rt"] }
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread", "time"] }
# In-process iroh-relay for testing the host-runtime feature: real
# AccessConfig::Restricted relay, real endpoint bind, real WebSocket
# upgrade. Same dev-dep iroh feature combo `mesh-llm-host-runtime`
# already uses for its own gated-relay tests.
iroh = { version = "1.0.0-rc.0", features = ["test-utils"] }
iroh-relay = { version = "1.0.0-rc.0", features = ["server", "test-utils"] }
futures-util = "0.3"
base64 = "0.22"
serde_json = "1"
48 changes: 48 additions & 0 deletions crates/mesh-llm-api-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,51 @@ high-level serving errors.
If an API is meant for client-only app integration, it belongs in
`mesh-llm-api-client`. If it requires model management or local serving, it
belongs in `mesh-llm-api-server`.

## Running the full mesh-llm runtime in-process (`host-runtime` feature)

For applications that want to run **exactly what `mesh-llm serve` /
`mesh-llm client` does** — not just consume mesh inference, but be the
running node — enable the `host-runtime` feature:

```toml
mesh-llm-api-server = { version = "0.66.0", features = ["host-runtime"] }
```

Then call `run_serve(MeshServeSpec { ... })`:

```rust
use mesh_llm_api_server::{run_serve, MeshServeSpec};
use std::collections::HashMap;

let mut relay_auths = HashMap::new();
relay_auths.insert(
"https://gated.example/".to_string(),
"<bearer>".to_string(),
);

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

This drives the same `runtime::run_with_args` entry point the binary
uses. You get auto-discovery, election, tunnel manager, OpenAI HTTP
proxy on `--port`, management console on `--console`, local model
serving (when configured), plugin host — the entire mesh-llm runtime
inside your process.

`MeshNode::builder()` (`host-runtime` feature also required for the
fine-grained options like `.relay(...)` and `.relay_auth(...)`) is the
composable alternative for apps that want to wire pieces themselves
rather than running the whole orchestration. See `docs/SDK.md` for the
full comparison.
56 changes: 52 additions & 4 deletions crates/mesh-llm-api-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,59 @@ pub use mesh_llm_api_client::{
MAX_RECONNECT_ATTEMPTS,
};
pub use mesh_llm_node::serving::ServingController;

/// Run the full mesh-llm runtime in-process — the same code path the
/// `mesh-llm` binary runs. Only available with the `host-runtime` feature.
///
/// This is the SDK entry point for embedders who want their Rust app to
/// act exactly like running `mesh-llm serve` or `mesh-llm client` —
/// with auto-discovery, election, tunnel manager, OpenAI HTTP proxy,
/// management console, and local model serving (when configured) —
/// without spawning the binary as a subprocess.
///
/// # Example
///
/// ```no_run
/// # use std::collections::HashMap;
/// use mesh_llm_api_server::{run_serve, MeshServeSpec};
///
/// # async fn run() -> anyhow::Result<()> {
/// let mut relay_auths = HashMap::new();
/// relay_auths.insert(
/// "https://gated.example/".to_string(),
/// "<nip98-bearer-or-static-token>".to_string(),
/// );
///
/// run_serve(MeshServeSpec {
/// // Same flags `mesh-llm serve` / `mesh-llm client` accept.
/// client: true, // false (default) = serve role
/// auto: true, // == --auto
/// relays: vec!["https://gated.example/".into()],
/// relay_auths, // == --relay-auth URL=TOKEN
/// port: Some(9337), // OpenAI HTTP proxy port
/// console_port: Some(3131), // management API / web console
/// headless: true, // skip embedded web UI
/// max_vram_gb: Some(0.0), // client-only, no VRAM advert
/// ..MeshServeSpec::default()
/// })
/// .await?;
/// # Ok(())
/// # }
/// ```
///
/// The future blocks until the runtime exits. The runtime is not
/// currently `Send`-clean; if you need concurrent work, run on a
/// `tokio::task::LocalSet` rather than `tokio::spawn`.
///
/// For finer-grained control — composing pieces without running the
/// whole orchestration — see [`MeshNodeBuilder`] instead.
#[cfg(feature = "host-runtime")]
pub use mesh_llm_host_runtime::host_node::{run_serve, MeshServeSpec};
pub use node::{
CapabilityLevel, CleanupPolicy, CleanupResult, DeleteModelOptions, DeleteModelResult,
DevicePolicy, DownloadId, DownloadOptions, DownloadedModel, InstalledModel, LoadModelOptions,
MeshEvents, MeshInference, MeshModels, MeshNode, MeshNodeBuilder, MeshNodeConfig, MeshServing,
MeshStatusApi, ModelCacheStatus, ModelCapabilities, ModelDetails, ModelKind, ModelSearchQuery,
ModelSource, ModelSummary, PrunePolicy, PruneResult, ServedModel, ServingModelState,
ServingStatus, UnloadModelOptions, UnloadTarget,
MeshEvents, MeshInference, MeshModels, MeshNode, MeshNodeBuilder, MeshNodeConfig, MeshQuicBind,
MeshRole, MeshServing, MeshStatusApi, ModelCacheStatus, ModelCapabilities, ModelDetails,
ModelKind, ModelSearchQuery, ModelSource, ModelSummary, PrunePolicy, PruneResult, ServedModel,
ServingModelState, ServingStatus, UnloadModelOptions, UnloadTarget,
};
Loading
Loading