mesh-llm/docs/sdk/node.md
Michael Neale 97c0cad991
feat: native rust SDK for rust consumers. (#736)
* a run at SDK, tested with a client

* Use in-process shutdown for embedded SDK

* Satisfy clippy for embedded shutdown plumbing

* Document embedded Rust SDK usage

* Add public Rust SDK crate

* Tighten embedded SDK lifecycle

* Address embedded SDK review feedback

* Document native runtime packaging direction

* Document runtime CLI namespace

* Document runtime CLI UX expectations

* Document runtime diagnostics under doctor

* Add Windows PowerShell installer

* Document recommended runtime install flow

* Add native runtime resolver foundation

* Wire native runtime release installs

* Document native runtime crate

* Load versioned native runtimes dynamically

* Fix embedded SDK output manager reset

* Expose SDK mesh admission controls

* Split SDK runtime mapping assertions

* Tighten SDK docs and config module

* Clarify native runtime SDK TODOs

* Stabilize native log note test

* Expose native runtime install SDK

* Re-export native runtime APIs from SDK crate

* Add embedded SDK knobs for Sprout relay mesh (#782)

Two opt-in seams the Sprout v1 mesh integration needs:

- disable_iroh_relays(bool): when true, embedded runtime selects an explicitly disabled relay policy, which uses RelayMode::Disabled, skips public relay URL fallback, skips raw STUN, and avoids the 5s endpoint.online() wait that cannot succeed without a home relay. Default false preserves existing behavior.

- EmbeddedNodeHandle::join_token(token): forwards an invite token over the runtime control channel to node.join_with_retry so an already-running embedded node can dial a new EndpointAddr without restart. Handled in both auto and passive/client runtime loops.

Purely additive; existing defaults and startup join_tokens behavior remain unchanged.

Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Perci <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>

* Fix relay policy test visibility

* Make SDK publishable and align language bindings (#771)

* Split SDK native runtime publish surface

* Split CLI and TUI support crates

* Move CLI parser surface into mesh-llm-cli

* Extract shared mesh event surface

* Move standalone command handlers out of host runtime

* Move benchmark and plugin commands out of host runtime

* Finish plugin command extraction

* Extract auth identity ownership

* Move remaining standalone commands out of host runtime

* Move model store into model-hf

* Move CLI commands out of host runtime

* Decouple host runtime from CLI and TUI crates

* Expose embedded node SDK facade

* Keep client identity dependencies pure

* Simplify Rust SDK feature surface

* Keep SDK client feature runtime-free

* Expose SDK client API base override

* Use direct mesh SDK client transport

* Remove API base URL client builder shim

* Align language SDKs with Rust SDK facade

* Document SDK client and serving modes

* Fix SDK smoke runtime setup

* Package SDK console assets

* Fix dynamic runtime CI setup

* Restructure SDK docs by language

* Fix SDK smoke package loading

* Fix native runtime bundle resolution

* Add structured native runtime backend metadata

* Harden Kotlin native runtime smoke resolution

* Fix mesh-llm-sdk clippy imports

* Retry smoke model downloads

---------

Co-authored-by: James Dumay <jameswdumay@gmail.com>
Co-authored-by: tlongwell-block <109685178+tlongwell-block@users.noreply.github.com>
Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Perci <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
2026-06-03 12:39:19 +10:00

3.4 KiB

Node.js SDK

Use @meshllm/sdk from npm for Node.js and Electron applications.

Install

{
  "dependencies": {
    "@meshllm/sdk": "0.68.0"
  }
}

When building from this repository, build the native N-API addon first:

cd sdk/node
npm run build:native

Client: Public Mesh

Node.js public discovery helpers are not currently exported by @meshllm/sdk. Use a public invite token selected by your app or service.

const { Client, generateOwnerKeypairHex } = require('@meshllm/sdk')

const client = Client.create({
  ownerKeypairHex: generateOwnerKeypairHex(),
  inviteToken: process.env.MESH_PUBLIC_INVITE
})

await client.start()
const models = await client.inference.listModels()
const result = await client.inference.chat({
  model: models[0].id,
  messages: [{ role: 'user', content: 'Say hello from a public mesh.' }]
})
console.log(result.content)
await client.stop()

Client: Private Mesh

const { Client, generateOwnerKeypairHex } = require('@meshllm/sdk')

const client = Client.create({
  ownerKeypairHex: generateOwnerKeypairHex(),
  inviteToken: process.env.MESH_PRIVATE_INVITE
})

await client.start()
const models = await client.inference.listModels()
const result = await client.inference.chat({
  model: models[0].id,
  messages: [{ role: 'user', content: 'Say hello from a private mesh.' }]
})
console.log(result.content)
await client.stop()

Serving: Install Runtime

Install or resolve a native runtime before starting local serving:

const { resolveNativeRuntime } = require('@meshllm/sdk')

await resolveNativeRuntime({
  artifactDir: process.env.MESHLLM_NATIVE_RUNTIME_ARTIFACT_DIR,
  allowDownload: process.env.MESH_SDK_RUNTIME_ALLOW_DOWNLOAD === '1',
  onProgress: (event) => console.log(event)
})

Serving: Public Mesh

const { Node, generateOwnerKeypairHex, resolveNativeRuntime } = require('@meshllm/sdk')

await resolveNativeRuntime({
  artifactDir: process.env.MESHLLM_NATIVE_RUNTIME_ARTIFACT_DIR,
  allowDownload: process.env.MESH_SDK_RUNTIME_ALLOW_DOWNLOAD === '1',
  onProgress: (event) => console.log(event)
})

const modelRef = process.env.MESH_SDK_MODEL_REF || 'Qwen2.5-3B-Instruct-Q4_K_M'
const node = Node.create({
  ownerKeypairHex: generateOwnerKeypairHex(),
  inviteToken: process.env.MESH_PUBLIC_INVITE,
  servingEnabled: true,
  cacheDir: process.env.MESH_SDK_CACHE_DIR,
  runtimeDir: process.env.MESH_SDK_RUNTIME_DIR
})

await node.start()
await node.models.download(modelRef)
const served = await node.serving.load(modelRef, { devicePolicy: 'auto' })
const result = await node.inference.chat({
  model: served.modelId,
  messages: [{ role: 'user', content: 'Say hello from a public serving node.' }]
})
console.log(result.content)
await node.serving.unloadModel(served.modelId)
await node.stop()

Serving: Private Mesh

Private mesh serving uses the same lifecycle with MESH_PRIVATE_INVITE:

const node = Node.create({
  ownerKeypairHex: generateOwnerKeypairHex(),
  inviteToken: process.env.MESH_PRIVATE_INVITE,
  servingEnabled: true,
  cacheDir: process.env.MESH_SDK_CACHE_DIR,
  runtimeDir: process.env.MESH_SDK_RUNTIME_DIR
})

Console Assets

Published Node packages that advertise console support include the built web console as package resources. Use the package helper to find those assets in normal package usage:

const { defaultConsoleAssetDir } = require('@meshllm/sdk')

const assetDir = defaultConsoleAssetDir()