Skip to content

feature: add embedded SDK support#233

Open
ndizazzo wants to merge 27 commits intomainfrom
feature/native-embedded-sdks
Open

feature: add embedded SDK support#233
ndizazzo wants to merge 27 commits intomainfrom
feature/native-embedded-sdks

Conversation

@ndizazzo
Copy link
Copy Markdown
Collaborator

@ndizazzo ndizazzo commented Apr 10, 2026

This branch adds an embedded Mesh SDK stack for app integrations.

After this change, app runtimes can embed a Mesh client directly instead of treating Mesh as a localhost-only sidecar. The branch introduces a public Rust SDK surface, a UniFFI layer for native bindings, and native Swift and Kotlin packages built on top of the same client core.

This branch also adds CI coverage for the embedded client path, so SDK consumers are validated against a real served model rather than only through the CLI and server workflows.

Closes #188

Architecture

The branch defines the embedded SDK layering explicitly:

  • mesh-client is the internal client implementation crate.
  • mesh-api is the public Rust SDK for app integrations such as Jan.
  • mesh-api-ffi is the UniFFI/native bindings layer.
  • Swift and Kotlin bindings sit on top of mesh-api-ffi.

That gives the repo one shared client core with separate product-facing surfaces for Rust and native mobile/desktop consumers.

Protocol

This branch is not intended to introduce a breaking mesh protocol change.

  • Existing protocol compatibility coverage remains in place.
  • The embedded SDK work is about packaging and client integration surfaces, not changing mesh wire semantics.

Validation

Validated locally:

  • cargo test -p mesh-llm --test protocol_compat_v0_client
  • cargo test -p mesh-llm --test protocol_convert_matrix
  • scripts/ci-native-sdk-smoke.sh target/debug/mesh-llm llama.cpp/build/bin ~/.models/SmolLM2-135M-Instruct-Q8_0.gguf
  • scripts/ci-kotlin-sdk-smoke.sh target/debug/mesh-llm llama.cpp/build/bin ~/.models/SmolLM2-135M-Instruct-Q8_0.gguf
  • scripts/ci-swift-sdk-smoke.sh target/debug/mesh-llm llama.cpp/build/bin ~/.models/SmolLM2-135M-Instruct-Q8_0.gguf

CI notes:

  • native_sdk_smoke and kotlin_sdk_smoke run after inference_smoke_tests.
  • The legacy macos lane is documented as a Linux cross-build lane and does not require a macOS runner.
  • swift_sdk_smoke is intentionally disabled until a Swift execution runner is available.

- extract a native embedded client SDK with Rust core, FFI bindings, and test harness support
- add Swift and Kotlin wrappers, packaging, smoke tests, and protocol compatibility coverage
- target iOS, macOS, and Android embedded-client flows without localhost sidecars
@ndizazzo ndizazzo self-assigned this Apr 10, 2026
i386 added 2 commits April 12, 2026 17:22
# Conflicts:
#	.github/workflows/ci.yml
#	mesh-llm/Cargo.toml
#	mesh-llm/src/api/routes/mod.rs
#	mesh-llm/src/inference/election.rs
#	mesh-llm/src/inference/moe.rs
#	mesh-llm/src/models/catalog.rs
#	mesh-llm/src/network/nostr.rs
#	mesh-llm/src/network/proxy.rs
#	mesh-llm/src/plugin/transport.rs
#	mesh-llm/src/runtime/mod.rs
@Mesh-LLM Mesh-LLM deleted a comment from Copilot AI Apr 12, 2026
@i386 i386 marked this pull request as ready for review April 12, 2026 22:13
Copilot AI review requested due to automatic review settings April 12, 2026 22:13
@i386 i386 assigned i386 and unassigned ndizazzo Apr 12, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR introduces an embedded Mesh SDK stack that allows app runtimes to embed a Mesh client directly (instead of depending on a localhost sidecar), with Rust, UniFFI, Swift, and Kotlin surfaces plus CI/smoke coverage.

Changes:

  • Added new Rust crates (mesh-client, mesh-api, mesh-api-ffi, mesh-host-core, mesh-llm-test-harness) and extracted/shared protocol/network/model logic for embedded use.
  • Added Swift and Kotlin SDK packaging, examples, and platform compliance artifacts (Swift privacy manifest; Android 16KB page alignment).
  • Added CI smoke/fixture scripts and protocol compatibility tests to validate embedded-client paths.

Reviewed changes

Copilot reviewed 128 out of 142 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
sdk/swift/Sources/MeshLLM/EventStream.swift Adds async streaming convenience + bridging logic for events/cancellation.
sdk/swift/README.md Documents Swift SDK install/usage and App Store compliance notes.
sdk/swift/PrivacyInfo.xcprivacy Adds Apple privacy manifest template for XCFramework.
sdk/swift/PrivacyInfo-README.md Documents privacy manifest embedding requirements and verification.
sdk/swift/Package.swift Adds SwiftPM package with optional binary XCFramework linkage.
sdk/swift/.gitignore Ignores Swift build dir and generated XCFramework.
sdk/kotlin/src/test/kotlin/ai/meshllm/MeshClientTest.kt Adds Kotlin unit tests for flow cancellation and event ordering.
sdk/kotlin/src/main/kotlin/uniffi/mesh_ffi/MeshFfi.kt Defines Kotlin-side UniFFI DTOs and handle interfaces.
sdk/kotlin/src/main/kotlin/ai/meshllm/MeshClient.kt Implements Kotlin client wrapper, DTO mapping, and Flow APIs.
sdk/kotlin/src/main/jniLibs/.gitignore Ignores generated Android .so build outputs.
sdk/kotlin/src/main/AndroidManifest.xml Adds minimal manifest required for AAR packaging.
sdk/kotlin/settings.gradle.kts Defines Kotlin SDK Gradle root project name.
sdk/kotlin/scripts/verify-alignment.sh Adds Android 16KB page-size alignment verification script.
sdk/kotlin/ndk-version.txt Pins the NDK version used for native builds.
sdk/kotlin/gradlew Adds Gradle wrapper script for Kotlin SDK.
sdk/kotlin/gradle/wrapper/gradle-wrapper.properties Pins Gradle distribution for Kotlin SDK.
sdk/kotlin/example/example-jvm/src/main/kotlin/ai/meshllm/example/ExampleMain.kt Adds JVM example app that uses JNA + Kotlin bindings.
sdk/kotlin/example/example-jvm/settings.gradle.kts Defines example JVM project name.
sdk/kotlin/example/example-jvm/gradlew Adds Gradle wrapper to the JVM example subproject.
sdk/kotlin/example/example-jvm/gradle/wrapper/gradle-wrapper.properties Pins Gradle for the JVM example.
sdk/kotlin/example/example-jvm/build.gradle.kts Configures Kotlin/JVM example build + sourceset wiring.
sdk/kotlin/consumer-proguard-rules.pro Adds keep rules for consumer minification.
sdk/kotlin/build.gradle.kts Adds Kotlin SDK build + native .so build task + AAR assembly.
sdk/kotlin/.gitignore Ignores Gradle metadata and build outputs.
sdk/README.md Documents multi-language SDK directory structure and layering.
scripts/ci-swift-sdk-smoke.sh Adds Swift SDK smoke test runner script.
scripts/ci-sdk-fixture.sh Adds shared CI fixture to stand up a real served model and export env.
scripts/ci-native-sdk-smoke.sh Adds Rust FFI live smoke runner using the shared fixture.
scripts/ci-kotlin-sdk-smoke.sh Adds Kotlin JVM example smoke runner using the shared fixture.
mesh-llm/tests/protocol_convert_matrix.rs Adds protocol conversion/validation matrix tests against extracted protocol API.
mesh-llm/tests/protocol_compat_v0_client.rs Adds ALPN/protocol-compat coverage for v0/v1 negotiation semantics.
mesh-llm/src/plugins/blackboard/mod.rs Exposes is_enabled() accessor for blackboard plugin state.
mesh-llm/src/plugins/blackboard/mcp.rs Adds dead-code allowances and MCP stdio server runner wiring.
mesh-llm/src/plugin/mod.rs Adds constant for blackboard capability with dead-code allowance.
mesh-llm/src/models/topology.rs Re-exports topology types from mesh-client and keeps helper inference fns.
mesh-llm/src/mesh/mod.rs Re-exports extracted mesh/model descriptor logic from mesh-client.
mesh-llm/src/api/assets.rs Switches console asset embedding to build-time env-selected include path.
mesh-llm/docs/JAN_MESH_API_INTEGRATION.md Adds Jan integration contract doc for embedded mesh-api.
mesh-llm/docs/EMBEDDED_CLIENT_ADR.md Adds ADR capturing embedded SDK design/tooling/compat guarantees.
mesh-llm/build.rs Sets MESH_LLM_CONSOLE_DIST env to real or fallback console dist dir.
mesh-llm/Cargo.toml Depends on extracted mesh-client (host-io) and adds dev-dep for tests.
mesh-llm-test-harness/tests/fixture.rs Adds (ignored) fixture test skeleton for harness validation.
mesh-llm-test-harness/src/lib.rs Implements FixtureMesh launcher to get a real invite token.
mesh-llm-test-harness/Cargo.toml Adds harness crate deps (reqwest blocking + serde_json + thiserror).
mesh-host-core/src/lib.rs Adds placeholder crate for host-side core.
mesh-host-core/Cargo.toml Adds host-core crate manifest and feature skeleton.
mesh-client/tests/tunnel_relay.rs Adds tunnel relay transfer test using mock transport IO.
mesh-client/tests/transport_mock.rs Adds mock transport IO behavior tests.
mesh-client/tests/runtime_thread_leak.rs Adds runtime thread-leak and shutdown behavior tests.
mesh-client/tests/reconnect_manual.rs Adds reconnect/disconnect behavior tests (manual semantics).
mesh-client/tests/reconnect_automatic.rs Adds reconnect attempt-cap and disconnect flag tests.
mesh-client/tests/public_api.rs Adds compile-time public API shape checks.
mesh-client/tests/protocol_wire.rs Adds extracted protocol wire-format tests and invariants.
mesh-client/tests/nostr_discovery.rs Adds discovery scoring/filtering tests for extracted nostr logic.
mesh-client/tests/network_router_extraction.rs Adds tests for router classification/complexity helpers.
mesh-client/tests/network_rewrite_extraction.rs Adds tests for port rewrite map behavior.
mesh-client/tests/network_affinity_extraction.rs Adds tests for affinity routing behavior.
mesh-client/tests/moe_ranking.rs Adds tests for MoE ranking assignment and artifact behaviors.
mesh-client/tests/models_extraction.rs Adds tests for catalog/capabilities/GGUF parsing extraction.
mesh-client/tests/mesh_types.rs Adds tests for mesh/model descriptor types and demand merge semantics.
mesh-client/tests/mesh_client_api.rs Adds tests for join/status/disconnect/cancel/list/chat/responses API surface.
mesh-client/tests/key_provider.rs Adds tests for in-memory key provider round-trip behavior.
mesh-client/tests/http_parse_test.rs Adds tests for minimal HTTP request parsing helpers.
mesh-client/tests/events.rs Adds tests that all event variants are emit-capable.
mesh-client/tests/election_extraction.rs Adds tests for extracted election helpers (bytes sizing + no-peers host).
mesh-client/tests/crypto_envelope.rs Adds tests for message seal/open and keypair bytes round-trip.
mesh-client/tests/cancel_idempotent.rs Adds tests that cancel is a no-op for unknown/completed IDs.
mesh-client/tests/cancel_active.rs Adds test that canceling active request emits failed/cancelled.
mesh-client/src/runtime.rs Implements a dedicated-thread Tokio runtime wrapper for embedded safety.
mesh-client/src/protocol/v0.rs Implements legacy v0 tunnel-map JSON decode in mesh-client.
mesh-client/src/protocol/convert.rs Implements canonical config hashing for protocol snapshots.
mesh-client/src/network/tunnel.rs Adds abstract relay logic over generic transport IO.
mesh-client/src/network/transport_iroh.rs Adds TransportIo adapter for iroh bi-streams.
mesh-client/src/network/transport.rs Defines TransportIo trait and in-memory mock implementation.
mesh-client/src/network/rewrite.rs Adds QUIC→TCP register-peer endpoint rewrite logic.
mesh-client/src/network/mod.rs Wires up extracted network modules.
mesh-client/src/models/topology.rs Adds topology model types in mesh-client.
mesh-client/src/models/mod.rs Exposes models modules and re-exports topology types.
mesh-client/src/models/catalog.rs Adds embedded model catalog parsing and helper APIs.
mesh-client/src/mesh/mod.rs Exposes extracted mesh types module.
mesh-client/src/lib.rs Defines mesh-client crate public modules and key re-exports.
mesh-client/src/inference/mod.rs Wires inference modules (election + moe).
mesh-client/src/inference/election.rs Adds extracted inference target types + selection helpers.
mesh-client/src/events.rs Adds client event enum + listener trait.
mesh-client/src/crypto/provider.rs Adds key provider trait + in-memory provider.
mesh-client/src/crypto/mod.rs Wires crypto modules and re-exports.
mesh-client/src/crypto/keys.rs Adds embedded-safe owner keypair generation/serialization.
mesh-client/src/crypto/error.rs Adds crypto error enum.
mesh-client/src/client/mod.rs Wires client builder module exports.
mesh-client/proto/node.proto Adds portable protobuf schema for node control-plane types.
mesh-client/build.rs Builds protobuf definitions for mesh-client.
mesh-client/README.md Documents purpose/scope/layering of mesh-client crate.
mesh-client/Cargo.toml Adds mesh-client dependencies and build tooling.
mesh-api/tests/public_api.rs Adds mesh-api compile-time API shape checks.
mesh-api/src/token.rs Adds InviteToken wrapper and parsing boundary around mesh-client token type.
mesh-api/src/lib.rs Exposes mesh-api public surface and re-exports.
mesh-api/src/identity.rs Adds OwnerKeypair wrapper and byte import/export helpers.
mesh-api/src/events.rs Adds mesh-api event surface and listener trait.
mesh-api/src/client.rs Implements public MeshClient wrapper + adapter mapping to mesh-client.
mesh-api/README.md Documents mesh-api role as the public Rust SDK surface.
mesh-api/Cargo.toml Adds mesh-api manifest and feature passthrough.
mesh-api-ffi/tests/smoke.rs Adds basic ffi surface tests and placeholders for fixture-driven live smoke.
mesh-api-ffi/tests/live_sdk_smoke.rs Adds live mesh smoke test driven via CI fixture env vars.
mesh-api-ffi/tests/error_mapping.rs Adds tests enforcing ffi error mapping surface.
mesh-api-ffi/tests/client_exports_compile.rs Adds compile-time checks for exported FFI surface.
mesh-api-ffi/src/mesh_ffi.udl Defines UniFFI UDL surface for embedded client handle and DTOs.
mesh-api-ffi/src/lib.rs Implements UniFFI exports, DTO mapping, and sync wrappers via pollster.
mesh-api-ffi/build.rs Generates UniFFI scaffolding at build time.
mesh-api-ffi/README.md Documents purpose/layout of mesh-api-ffi crate.
mesh-api-ffi/Cargo.toml Adds UniFFI crate config and feature skeleton.
Cargo.toml Adds new crates to workspace members.
CONTRIBUTING.md Adds protocol backward-compat guidance and local test commands.
.github/workflows/ci.yml Adds embedded dependency purity checks and SDK smoke CI jobs.
.cargo/config.toml Adds Android 16KB page alignment linker flags for relevant targets.

Comment thread mesh-api-ffi/src/lib.rs
Comment thread sdk/swift/Sources/MeshLLM/EventStream.swift
Comment thread sdk/kotlin/build.gradle.kts Outdated
Comment thread scripts/ci-sdk-fixture.sh Outdated
Comment thread CONTRIBUTING.md Outdated
Copilot AI review requested due to automatic review settings April 13, 2026 03:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds an embedded SDK stack (Rust mesh-api, UniFFI bridge, Swift/Kotlin packages) so app runtimes can embed a Mesh client directly (no localhost sidecar), plus CI/smoke coverage and protocol-compat tests.

Changes:

  • Introduces new Rust crates: mesh-client (core), mesh-api (public SDK), mesh-api-ffi (UniFFI), mesh-host-core (placeholder), and mesh-llm-test-harness.
  • Adds Swift + Kotlin SDK packaging (SwiftPM + Kotlin AAR/JVM example) and CI scripts for native/Kotlin/Swift smoke runs.
  • Adds protocol compatibility test suites and CI checks for embedded-client dependency purity + Android 16KB page alignment flags.

Reviewed changes

Copilot reviewed 129 out of 144 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
sdk/swift/Sources/MeshLLM/EventStream.swift Swift async stream bridging for event streaming + cancellation behavior.
sdk/swift/README.md Swift SDK installation/usage + App Store compliance notes.
sdk/swift/PrivacyInfo.xcprivacy Apple privacy manifest template for XCFramework embedding.
sdk/swift/PrivacyInfo-README.md Documentation for embedding/verifying privacy manifest in the XCFramework.
sdk/swift/Package.swift SwiftPM package definition with optional UniFFI XCFramework binary target.
sdk/swift/.gitignore Ignores Swift build artifacts and generated XCFramework.
sdk/kotlin/src/test/kotlin/ai/meshllm/MeshClientTest.kt Kotlin unit tests validating flow ordering and cancellation behavior.
sdk/kotlin/src/main/kotlin/uniffi/mesh_ffi/MeshFfi.kt Kotlin-side UniFFI DTOs/interfaces used by the Kotlin SDK layer.
sdk/kotlin/src/main/kotlin/ai/meshllm/MeshClient.kt Kotlin SDK client wrapper + Flow-based streaming helpers.
sdk/kotlin/src/main/jniLibs/.gitignore Ignores generated Android .so artifacts in source tree.
sdk/kotlin/src/main/AndroidManifest.xml Minimal manifest required for AAR packaging.
sdk/kotlin/settings.gradle.kts Kotlin SDK Gradle project naming.
sdk/kotlin/scripts/verify-alignment.sh Script to verify Android 16KB LOAD segment alignment in .so.
sdk/kotlin/ndk-version.txt NDK version pin for reproducible Android native builds.
sdk/kotlin/gradlew Gradle wrapper script for Kotlin SDK project.
sdk/kotlin/gradle/wrapper/gradle-wrapper.properties Gradle wrapper distribution pin for Kotlin SDK project.
sdk/kotlin/example/example-jvm/src/main/kotlin/ai/meshllm/example/ExampleMain.kt JVM example app showing Kotlin SDK usage via JNA + generated bindings.
sdk/kotlin/example/example-jvm/settings.gradle.kts JVM example Gradle project naming.
sdk/kotlin/example/example-jvm/gradlew Gradle wrapper script for JVM example.
sdk/kotlin/example/example-jvm/gradle/wrapper/gradle-wrapper.properties Gradle wrapper pin for JVM example.
sdk/kotlin/example/example-jvm/build.gradle.kts JVM example build config + dependency and sourceSets wiring.
sdk/kotlin/consumer-proguard-rules.pro Consumer ProGuard rules for Android AAR consumers.
sdk/kotlin/build.gradle.kts Kotlin SDK build: native .so build task + custom AAR assembly.
sdk/kotlin/.gitignore Ignores Gradle caches/build outputs for Kotlin SDK.
sdk/README.md Top-level SDK directory overview + layering guidance.
scripts/ci-swift-sdk-smoke.sh CI script to build Swift XCFramework and run Swift SDK smoke test.
scripts/ci-sdk-fixture.sh Shared CI fixture to run a real served model + export env for SDK tests.
scripts/ci-native-sdk-smoke.sh CI script to run Rust/FFI live SDK smoke test against fixture.
scripts/ci-kotlin-sdk-smoke.sh CI script to run Kotlin JVM example against live fixture.
mesh-llm/tests/protocol_convert_matrix.rs Protocol conversion matrix tests against mesh-client::protocol.
mesh-llm/tests/protocol_compat_v0_client.rs ALPN + v0/v1 compatibility tests against public protocol API.
mesh-llm/src/plugins/blackboard/mod.rs Adds is_enabled() accessor to blackboard store.
mesh-llm/src/plugins/blackboard/mcp.rs MCP server wiring improvements + stdio transport entrypoint.
mesh-llm/src/plugin/mod.rs Adds a blackboard capability constant (currently dead-code allowed).
mesh-llm/src/models/topology.rs Switches topology types to re-export from mesh-client.
mesh-llm/src/mesh/mod.rs Re-exports shared mesh types from mesh-client and trims duplicated defs.
mesh-llm/src/mesh/gossip.rs Removes local merge_demand in favor of shared mesh-client version.
mesh-llm/src/api/assets.rs Makes console asset embedding path configurable via build-time env var.
mesh-llm/docs/JAN_MESH_API_INTEGRATION.md Integration contract doc for embedding mesh-api in Jan (Tauri).
mesh-llm/docs/EMBEDDED_CLIENT_ADR.md ADR defining embedded SDK architecture + constraints + compatibility policy.
mesh-llm/build.rs Sets MESH_LLM_CONSOLE_DIST env and provides fallback when UI dist absent.
mesh-llm/Cargo.toml Adds mesh-client dependency (host-io) + dev-dep for tests.
mesh-llm-test-harness/tests/fixture.rs Adds initial (ignored) test harness coverage.
mesh-llm-test-harness/src/lib.rs Implements a fixture runner that spawns mesh-llm and polls /api/status.
mesh-llm-test-harness/Cargo.toml New crate config for the harness (blocking reqwest + serde_json).
mesh-host-core/src/lib.rs Placeholder crate for future host-core extraction.
mesh-host-core/Cargo.toml New crate stub + feature scaffolding.
mesh-client/tests/tunnel_relay.rs Tests for abstract tunnel relay copying bytes across transport IO.
mesh-client/tests/transport_mock.rs Tests for the mock transport implementation.
mesh-client/tests/runtime_thread_leak.rs Tests runtime drop behavior and thread leak prevention.
mesh-client/tests/reconnect_manual.rs Tests manual reconnect/disconnect event emission semantics.
mesh-client/tests/reconnect_automatic.rs Tests reconnect counters/flags + max attempts constant.
mesh-client/tests/public_api.rs Compile-time public API shape tests for mesh-client.
mesh-client/tests/protocol_wire.rs Wire/protocol integration tests for ALPN + frame (de)serialization.
mesh-client/tests/nostr_discovery.rs Tests for Nostr discovery scoring/filtering logic.
mesh-client/tests/network_router_extraction.rs Tests for request classification + split-suffix stripping.
mesh-client/tests/network_rewrite_extraction.rs Tests for PortRewriteMap creation and behavior.
mesh-client/tests/network_affinity_extraction.rs Tests for sticky affinity routing behavior.
mesh-client/tests/moe_ranking.rs Tests for MoE ranking/assignment algorithms + cached artifact utilities.
mesh-client/tests/models_extraction.rs Tests for model catalog and minimal GGUF parsing behavior.
mesh-client/tests/mesh_types.rs Tests for shared mesh types + demand merge + descriptor inference behavior.
mesh-client/tests/mesh_client_api.rs Tests for high-level client lifecycle methods + request id generation.
mesh-client/tests/key_provider.rs Tests for in-memory key provider behavior.
mesh-client/tests/http_parse_test.rs Tests for HTTP parsing utilities used in proxy/relay paths.
mesh-client/tests/events.rs Tests for event types and listener emission.
mesh-client/tests/election_extraction.rs Tests for election helpers + file size accounting.
mesh-client/tests/crypto_envelope.rs Tests for crypto envelope seal/open and keypair byte roundtrip.
mesh-client/tests/cancel_idempotent.rs Tests cancel behavior on unknown/completed request IDs.
mesh-client/tests/cancel_active.rs Tests cancel behavior emits a failed/cancelled event.
mesh-client/src/runtime.rs Dedicated-thread Tokio runtime implementation for embedded safety.
mesh-client/src/protocol/v0.rs Legacy JSON tunnel-map decode for v0 protocol compatibility.
mesh-client/src/protocol/convert.rs Canonical config hashing for protocol conversion/validation.
mesh-client/src/network/tunnel.rs Abstract relay trait + generic byte relay function over TransportIo.
mesh-client/src/network/transport_iroh.rs TransportIo adapter for iroh bi-streams.
mesh-client/src/network/transport.rs Core TransportIo trait + in-memory mock implementation.
mesh-client/src/network/rewrite.rs REGISTER_PEER relay rewrite logic for orchestrator port mappings.
mesh-client/src/network/mod.rs Exposes network modules for embedded client core.
mesh-client/src/models/topology.rs Shared model topology DTOs (serde) used across client/host.
mesh-client/src/models/mod.rs Models module exports and re-exports.
mesh-client/src/models/catalog.rs Bundled model catalog loader + helpers for HF resolve URL parsing.
mesh-client/src/mesh/mod.rs Mesh module surface re-export.
mesh-client/src/lib.rs mesh-client crate root + public exports.
mesh-client/src/inference/mod.rs Inference module manifest.
mesh-client/src/inference/election.rs Election/routing types and helper(s) extracted for embedded core.
mesh-client/src/events.rs Embedded-client event types + listener trait.
mesh-client/src/crypto/provider.rs Key provider trait + in-memory provider implementation.
mesh-client/src/crypto/mod.rs Crypto module exports wiring.
mesh-client/src/crypto/keys.rs Owner keypair implementation + owner-id derivation.
mesh-client/src/crypto/error.rs Crypto error type definitions.
mesh-client/src/client/mod.rs Client module exports wiring.
mesh-client/proto/node.proto Extracted protobuf schema for node protocol v1 control plane.
mesh-client/build.rs Builds protobuf definitions with vendored protoc.
mesh-client/README.md Crate purpose + layering guidance for mesh-client.
mesh-client/Cargo.toml New crate dependencies/features for embedded client core.
mesh-api/tests/public_api.rs Compile-time public API shape tests for mesh-api.
mesh-api/src/token.rs Public InviteToken newtype bridging to mesh-client.
mesh-api/src/lib.rs mesh-api crate root exports.
mesh-api/src/identity.rs Public OwnerKeypair wrapper + hex serialization.
mesh-api/src/events.rs Public mesh-api event types and listener trait.
mesh-api/src/client.rs Public SDK ClientBuilder + MeshClient surface wrapping mesh-client.
mesh-api/README.md Crate purpose + guidance for Rust consumers.
mesh-api/Cargo.toml New crate dependencies/features.
mesh-api-ffi/tests/smoke.rs Unit tests for FFI handle creation, status, cancel, and event bridging.
mesh-api-ffi/tests/live_sdk_smoke.rs Live smoke test against a real served model via CI fixture.
mesh-api-ffi/tests/error_mapping.rs Tests for FFI error mapping + exported error trait assertions.
mesh-api-ffi/tests/client_exports_compile.rs Compile-time tests ensuring exports and listener types are usable.
mesh-api-ffi/src/mesh_ffi.udl UniFFI UDL defining exported client handle surface and DTOs.
mesh-api-ffi/src/lib.rs UniFFI Rust implementation for MeshClientHandle and type mappings.
mesh-api-ffi/build.rs UniFFI scaffolding generation configuration.
mesh-api-ffi/README.md Crate purpose + layering guidance for bindings.
mesh-api-ffi/Cargo.toml Crate config for UniFFI packaging + optional host feature.
Cargo.toml Adds new SDK crates to the workspace members list.
CONTRIBUTING.md Documents protocol backward-compatibility testing requirements.
.github/workflows/ci.yml Adds embedded-client purity check + protocol matrix tests + SDK smoke jobs.
.cargo/config.toml Adds Android linker flags for 16KB page-size alignment across targets.

Comment thread mesh-api-ffi/src/mesh_ffi.udl
Comment thread sdk/kotlin/src/test/kotlin/ai/meshllm/MeshClientTest.kt
Comment thread .github/workflows/ci.yml Outdated
Comment thread sdk/swift/Sources/MeshLLM/EventStream.swift Outdated
Comment thread mesh-llm-test-harness/src/lib.rs Outdated
Comment thread sdk/kotlin/build.gradle.kts Outdated
@i386
Copy link
Copy Markdown
Collaborator

i386 commented Apr 13, 2026

@copilot apply changes based on the comments in this thread

@i386
Copy link
Copy Markdown
Collaborator

i386 commented Apr 14, 2026

@copilot resolve the merge conflicts in this pull request

Copilot AI review requested due to automatic review settings April 14, 2026 05:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI review requested due to automatic review settings April 14, 2026 06:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@i386 i386 removed the experimental label Apr 16, 2026
# Conflicts:
#	Cargo.toml
#	mesh-llm/src/models/capabilities.rs
@ndizazzo
Copy link
Copy Markdown
Collaborator Author

So far it looks like we have a good portion of this already working, but we haven't reached the embedded SDK boundary yet. The overall structure of the branch looks right as far as I can tell:

  • the crate split is in place
  • Rust, FFI, and native layers are wired up
  • the public API surface is mostly defined
  • there's enough end to end scaffolding to make the intended direction clear

On the Rust side, everything I checked builds and tests cleanly. cargo build -p mesh-llm --bin mesh-llm passed, along with the targeted protocol tests, mesh-client tests, and mesh-api-ffi tests.

The Swift path is also usable locally. The XCFramework builds, a Swift exemplar project builds and runs, and the example and CI flow look like they can exercise a real request when the fixture environment is set up as expected.

The live smoke fixture works in bridged mode as well. CI and the native smoke setup can start mesh-llm, discover a model, send a request, and stream a completion through the SDK stack. As it stands, this branch already functions as a prototype native client for interacting with a local Mesh-LLM API backed runtime, and that part is solid.


Remaining workstreams

  1. Make mesh-client the real runtime
    Remove the dependency on MESH_CLIENT_API_BASE for the core happy path. join, list_models, chat, responses, cancel, status, disconnect, and reconnect should operate on real embedded transport and session state, not placeholder flags or fixture-only HTTP bridging.

  2. Restore shared core fidelity with mesh-llm
    Reconcile descriptor inference, capability inference, protocol definitions, and lifecycle semantics so the extracted crates aren't simplified forks. The embedded core should preserve the same behavior the host relies on.

  3. Make Swift and Kotlin honest wrappers over the Rust core
    Swift shouldn't silently fall back to a fake implementation for normal package consumers. Kotlin should ship a complete generated binding surface that matches the Rust FFI exactly, with an install and build path that works in a real external app.

  4. Make CI validate the shipped product boundary
    SDK changes should always trigger SDK validation. CI should prove the published consumer path, use the correct runtime dependencies, and test real embedded behavior instead of only a repo local smoke fixture.

# Conflicts:
#	Cargo.lock
#	mesh-llm/src/mesh/mod.rs
#	mesh-llm/src/models/capabilities.rs
#	mesh-llm/src/models/topology.rs
Copilot AI review requested due to automatic review settings April 16, 2026 22:51
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review is ineligible. To be eligible to request a review, you need a paid Copilot license, or your organization must enable Copilot code review.

@michaelneale
Copy link
Copy Markdown
Collaborator

Reviewed this — direction looks good and it's mostly additive, so low risk to existing mesh behavior. Two things worth raising before merge:

Proto duplication looks unintentional

mesh-llm/proto/node.proto and mesh-client/proto/node.proto both declare package meshllm.node.v1;, share most message names (GossipFrame, PeerAnnouncement, ServedModelDescriptor, NodeConfigSnapshot, ConfigPush, …), and both build.rs files generate into the same Rust module path. So they're the same schema, just duplicated.

The two copies have already drifted:

  • mesh-client's copy is missing HardwareInfo, GpuInfo, SignedNodeOwnership, ConfiguredModelRef — the attested-identity + hardware-gossip work that's on main.
  • Field 28 on NodeAnnouncement disagrees: mesh-llm has SignedNodeOwnership owner_attestation = 28, mesh-client has string owner_id = 28. Same wire tag, different types — peers built from one decode that field as garbage against peers built from the other.

Fix is structural rather than a resync: point both crates at a single .proto (either shared at workspace root, or one crate's build.rs reads the other's file). Makes it impossible to drift again.

Kotlin AAR ships stub bindings, not the real ones

sdk/kotlin/src/main/kotlin/uniffi/mesh_ffi/MeshFfi.kt is 67 lines of interface declarations with no implementation. The real generated UniFFI bindings (2111 lines) live under sdk/kotlin/example/example-jvm/. The packaged AAR picks up the stub, so consumers installing the artifact would get MeshClientHandleInterface with nothing implementing it and no JNI loader wired up.

kotlin_sdk_smoke passes because it exercises the example app, which has its own copy of the real bindings — not the library AAR consumers would actually depend on. Worth confirming which artifact is intended to ship.

Everything else (forked router/nostr/affinity copies in mesh-client vs mesh-llm, dep allowlist drift, a couple of FFI unwraps) is follow-up material, not blockers.

@michaelneale michaelneale requested a review from Copilot April 17, 2026 06:25
* main:
  fix: remove unintended PR job from 307
  v0.62.1: release
  add test job to check CI
  fix(cuda): remove compute_103 from supported platforms
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 129 out of 143 changed files in this pull request and generated 6 comments.

Comment thread .github/workflows/ci.yml
Comment on lines +135 to +137
if grep -wE "^\s*($FORBIDDEN)" /tmp/mesh-client-deps.txt; then
echo "ERROR: Forbidden dependency found in mesh-client"
grep -wE "^\s*($FORBIDDEN)" /tmp/mesh-client-deps.txt
Comment on lines +113 to +115
tasks.named("assembleAar") {
dependsOn(buildNativeLibs)
}
}
}

#if canImport(mesh_ffiFFI)
Comment on lines +77 to +90
private func cancelIfNeeded() {
stateLock.lock()
guard !finished else {
stateLock.unlock()
return
}
let requestId = self.requestId
stateLock.unlock()

guard let requestId else {
return
}
onCancel(requestId)
}

impl Drop for FixtureMesh {
fn drop(&mut self) {
// Send SIGTERM, wait up to 5s, then SIGKILL
Comment thread .github/workflows/ci.yml
Comment on lines +333 to +336
swift_sdk_smoke:
needs: [changes, inference_smoke_tests]
if: ${{ needs.inference_smoke_tests.result == 'success' && (github.event_name == 'workflow_dispatch' || needs.changes.outputs.rust == 'true' || needs.changes.outputs.ui == 'true') }}
runs-on: macos-latest
mesh-client previously carried its own copy of node.proto that had
diverged from mesh-llm's: it added owner_id filter fields on the
config messages (ConfigSubscribe, ConfigSnapshotResponse,
ConfigUpdateNotification, ConfigPush) but was missing the hardware
gossip additions (HardwareInfo, GpuInfo), attested-identity work
(SignedNodeOwnership), and pinned-GPU model fields that landed on
main after mesh-client forked.

The two files also collided on PeerAnnouncement field 28:
  mesh-llm    → SignedNodeOwnership owner_attestation
  mesh-client → string owner_id

This keeps mesh-llm/proto/node.proto as the canonical schema (since
it matches the deployed mesh) and ports the owner_id additions into
it at their original tag numbers — those tags happened to be free
in mesh-llm's version so no renumbering was required. Field 28 stays
as owner_attestation, matching production.

mesh-client/build.rs now compiles ../mesh-llm/proto/node.proto and
mesh-client/proto/ is removed, so the workspace has one schema.

Call sites updated to populate the new owner_id field:
- mesh-llm/src/mesh/mod.rs: empty string for error/outgoing paths,
  local_owner_id or snapshot.owner_id where meaningful
- test code in mesh/tests.rs and protocol/mod.rs
- tests/protocol_convert_matrix.rs: also needed the NodeModelEntry
  pinned-GPU fields (the other direction of the divergence)

Validated:
- cargo check --workspace: clean
- cargo test -p mesh-client: 83 lib + 188 integration pass
- cargo test -p mesh-llm --lib: 875 pass, 0 fail
- cargo test --test protocol_compat_v0_client --test protocol_convert_matrix: 11 pass
- cargo fmt --all -- --check: clean
…ating

Previously, passing an empty owner_keypair_bytes_hex to create_client
would silently call OwnerKeypair::generate() and produce a brand-new
identity. This is a footgun: a Swift/Kotlin app that fails to load its
persisted keypair (missing file, keychain miss, etc.) would get a
fresh identity every launch with no error surfaced to the caller.

Now an empty or whitespace-only keypair hex returns
FfiError::InvalidOwnerKeypair. Callers that genuinely want a new
identity should create one explicitly via OwnerKeypair::generate()
and pass its hex representation.

Updated existing smoke tests that passed "" as a placeholder to use
a generated keypair, and added a test that pins the new empty-input
rejection behavior.

Addresses GitHub Copilot review feedback on PR #233.
Copilot AI review requested due to automatic review settings April 17, 2026 06:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 131 out of 145 changed files in this pull request and generated 7 comments.

Comment thread mesh-api-ffi/tests/live_sdk_smoke.rs Outdated
Comment on lines +25 to +26
let handle = create_client(String::new(), invite_token).expect("create_client");
handle.join().expect("join");
Comment on lines +24 to +28
/// Old peers advertising only `mesh-llm/0` must be accepted with the JSON codec.
#[test]
fn protocol_from_alpn_v0_yields_json_v0() {
assert_eq!(protocol_from_alpn(ALPN_V0), ControlProtocol::JsonV0);
}
Comment thread .github/workflows/ci.yml
Comment on lines +135 to +137
if grep -wE "^\s*($FORBIDDEN)" /tmp/mesh-client-deps.txt; then
echo "ERROR: Forbidden dependency found in mesh-client"
grep -wE "^\s*($FORBIDDEN)" /tmp/mesh-client-deps.txt
Comment on lines +65 to +67
`mesh-client` has a strict dependency allowlist. Only these 18 crates are permitted:

`iroh`, `tokio`, `prost`, `bytes`, `rustls`, `quinn`, `serde`, `serde_json`, `thiserror`, `anyhow`, `tracing`, `sha2`, `ed25519-dalek`, `hex`, `uuid`, `url`, `http`, `base64`
Comment on lines +93 to +94
pub fn reconnect(&mut self) -> Result<(), MeshError>;
}
Comment on lines +77 to +90
private func cancelIfNeeded() {
stateLock.lock()
guard !finished else {
stateLock.unlock()
return
}
let requestId = self.requestId
stateLock.unlock()

guard let requestId else {
return
}
onCancel(requestId)
}
Comment thread mesh-api-ffi/src/lib.rs
Comment on lines +126 to +128
let client = ClientBuilder::new(kp, token)
.build()
.map_err(|_| FfiError::JoinFailed)?;
The earlier commit to reject empty owner keypairs in create_client
broke three live smoke paths that relied on passing "" to get an
auto-generated keypair:

- mesh-api-ffi/tests/live_sdk_smoke.rs: native SDK smoke
- sdk/kotlin/example/example-jvm: Kotlin SDK smoke
- sdk/swift/example/MeshExampleApp + Swift tests: Swift SDK smoke

Add a new FFI function, generate_owner_keypair_hex(), that callers use
to mint a keypair explicitly on first run and persist across launches.
All four example/test call sites now generate an explicit keypair and
pass it to create_client.

Also:
- Regenerate committed Swift bindings (mesh_ffi.swift, mesh_ffiFFI.h)
  via sdk/swift/scripts/generate-swift-bindings.sh so they expose the
  new function.
- Add sdk/kotlin/scripts/generate-kotlin-bindings.sh — the Kotlin side
  previously had no regeneration script. The library source set also
  carried a hand-written stub (MeshFfi.kt, 67 lines) that shadowed the
  real bindings; delete it and ship the generated mesh_ffi.kt in both
  the library and the example source sets, keeping them in lockstep.

Verified locally:
- cargo check --workspace: clean
- cargo fmt --all -- --check: clean
- cargo test -p mesh-api-ffi --test smoke: 9 passed (1 ignored)
- cargo test -p mesh-client: 83 lib + 188 integration pass
swift_sdk_smoke was cloning upstream-latest from a personal fork
(michaelneale/llama.cpp), while every other CI job builds from the
org fork (Mesh-LLM/llama.cpp) pinned to LLAMA_CPP_SHA. The personal
fork's branch lacks the --mesh-port patch mesh-llm now passes to
llama-server, so swift_sdk_smoke was failing with:

    error: invalid argument: --mesh-port

Use the same clone-and-checkout recipe the Linux/CUDA/ROCm/Vulkan
jobs use, so Swift builds the same llama.cpp binary as everything
else.
Copilot AI review requested due to automatic review settings April 17, 2026 07:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 124 out of 146 changed files in this pull request and generated 9 comments.

Comment on lines +113 to +115
tasks.named("assembleAar") {
dependsOn(buildNativeLibs)
}
Comment on lines +122 to +124
val assembleAar by tasks.registering(Zip::class) {
description = "Assemble AAR artifact with native libs and consumer ProGuard rules"
group = "build"

if [ ! -x "$BINDGEN" ]; then
echo "Installing uniffi-bindgen 0.31.0 into $BINDGEN_ROOT ..."
cargo install uniffi --version =0.31.0 --features cli --bin uniffi-bindgen \
Comment on lines +27 to +28
@JvmInline
value class RequestId(val value: String)
Comment on lines +34 to +36
data class TokenDelta(val requestId: String, val delta: String) : Event()
data class Completed(val requestId: String) : Event()
data class Failed(val requestId: String, val error: String) : Event()
Comment on lines +96 to +102
val requestId = chat(request) { event -> trySend(event) }
awaitClose { cancel(requestId) }
}

fun responsesFlow(request: ResponsesRequest): Flow<Event> = callbackFlow {
val requestId = responses(request) { event -> trySend(event) }
awaitClose { cancel(requestId) }
Comment thread mesh-api-ffi/src/lib.rs
Comment on lines +120 to +127
#[uniffi::export]
pub fn create_client(
owner_keypair_bytes_hex: String,
invite_token: String,
) -> Result<Arc<MeshClientHandle>, FfiError> {
let token = invite_token
.parse::<InviteToken>()
.map_err(|_| FfiError::InvalidInviteToken)?;
Comment thread mesh-api-ffi/src/lib.rs
Comment on lines +136 to +139
let kp = OwnerKeypair::from_hex(trimmed).map_err(|_| FfiError::InvalidOwnerKeypair)?;
let client = ClientBuilder::new(kp, token)
.build()
.map_err(|_| FfiError::JoinFailed)?;
Comment thread mesh-api-ffi/src/lib.rs
Comment on lines +147 to +154
pub fn join(&self) -> Result<(), FfiError> {
let mut client = self.inner.lock().unwrap();
block_on(client.join()).map_err(|_| FfiError::JoinFailed)
}

pub fn list_models(&self) -> Result<Vec<ModelDto>, FfiError> {
let client = self.inner.lock().unwrap();
let models = block_on(client.list_models()).map_err(|_| FfiError::DiscoveryFailed)?;
* origin/main:
  bump llama.cpp to e88186e78777
  Normalize MoE share refs for split GGUFs
  refactor(ui): share resolved theme hook across topology and mermaid
  feat: Implement light mode for topology diagram
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.

Add native embedded SDKs for Swift and Kotlin/Java using a shared Rust core

5 participants