HiveLLM.Synap.SDK 1.3.0

dotnet add package HiveLLM.Synap.SDK --version 1.3.0
                    
NuGet\Install-Package HiveLLM.Synap.SDK -Version 1.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HiveLLM.Synap.SDK" Version="1.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HiveLLM.Synap.SDK" Version="1.3.0" />
                    
Directory.Packages.props
<PackageReference Include="HiveLLM.Synap.SDK" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add HiveLLM.Synap.SDK --version 1.3.0
                    
#r "nuget: HiveLLM.Synap.SDK, 1.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package HiveLLM.Synap.SDK@1.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=HiveLLM.Synap.SDK&version=1.3.0
                    
Install as a Cake Addin
#tool nuget:?package=HiveLLM.Synap.SDK&version=1.3.0
                    
Install as a Cake Tool

Synap C# SDK

Official C# client library for Synap - High-Performance In-Memory Key-Value Store & Message Broker.

Features

  • 💾 Key-Value Store: Fast in-memory KV operations with TTL support
  • 📨 Message Queues: RabbitMQ-style queues with ACK/NACK
  • 📡 Event Streams: Kafka-style event streams with offset tracking
  • 🔔 Pub/Sub: Topic-based messaging with wildcards
  • StreamableHTTP Protocol: Unified endpoint for all operations
  • 🛡️ Type-Safe: Leverages C# 12+ type system for correctness
  • 📦 Async/Await: Built on modern async patterns with ConfigureAwait

Requirements

  • .NET 8.0 or higher
  • Synap Server running

Installation

dotnet add package HiveHub.Synap.SDK

Quick Start

using Synap.SDK;

// Create client — SynapRPC (the fastest transport) is the default scheme;
// resp3:// and http:// URLs are also accepted.
var config = SynapConfig.Create("synap://localhost:15501");
var client = new SynapClient(config);

// Key-Value operations
await client.KV.SetAsync("user:1", "John Doe");
var value = await client.KV.GetAsync<string>("user:1");
Console.WriteLine($"Value: {value}");

// Queue operations
await client.Queue.CreateQueueAsync("tasks");
var msgId = await client.Queue.PublishAsync("tasks", new { task = "process-video" }, priority: 9);
var message = await client.Queue.ConsumeAsync("tasks", "worker-1");

if (message is not null)
{
    // Process message
    Console.WriteLine($"Received: {message.Payload}");
    await client.Queue.AckAsync("tasks", message.Id);
}

// Event Stream
await client.Stream.CreateRoomAsync("chat-room-1");
var offset = await client.Stream.PublishAsync("chat-room-1", "message", new
{
    user = "alice",
    text = "Hello!"
});

// Pub/Sub
await client.PubSub.SubscribeTopicsAsync("user-123", new List<string> { "notifications.*" });
var delivered = await client.PubSub.PublishAsync("notifications.email", new
{
    to = "user@example.com",
    subject = "Welcome"
});

// Dispose client when done
client.Dispose();

Transports

Since v0.11.0 the SDK selects the transport via URL scheme — no builder methods required:

URL scheme Default port When to use
synap:// 15501 ✅ Recommended default — MessagePack over persistent TCP, lowest latency.
resp3:// 6379 Redis-compatible text protocol — interop with existing Redis tooling.
http:// / https:// 15500 Original REST transport — full command coverage.

All commands (KV, Hash, List, Set, Sorted Set, Queue, Stream, Pub/Sub, Transactions, Scripts, Geo, HyperLogLog) are fully supported on every transport. Native transports throw UnsupportedCommandException instead of silently falling back to HTTP.

using Synap.SDK;

// SynapRPC — recommended default
var client = new SynapClient(SynapConfig.Create("synap://127.0.0.1:15501"));

// RESP3 — Redis-compatible
var client = new SynapClient(SynapConfig.Create("resp3://127.0.0.1:6379"));

// HTTP — full REST access
var client = new SynapClient(SynapConfig.Create("http://127.0.0.1:15500"));

The synap:// transport is Thunder

The binary transport is not hand-written in this SDK. It is Thunder (HiveLLM.Thunder) — the HiveLLM family's shared binary RPC client, the same protocol the Synap server runs on, so the two ends of the wire cannot drift.

Pipelining Concurrent commands multiplex over one connection, demultiplexed by frame id.
Frame cap 512 MiB, validated against the length prefix before allocating. The previous transport ran new byte[msgLen] with whatever a 4-byte prefix claimed.
Timeouts Connect and per-call, both from SynapConfig.Timeout.
Reconnect Lazy, with capped retries.
Authentication WithAuthToken / WithBasicAuth credentials travel in the handshake — the previous transport never sent AUTH, so it could not reach a require_auth server on 15501.
Push SUBSCRIBE delivery uses Thunder's push hook. The previous implementation sent SUBSCRIBE with id = 0xFFFFFFFF, the reserved push sentinel, which a Thunder server refuses outright.

Queue, stream and pub/sub over synap://:

using Synap.SDK;

await using var client = new SynapClient(SynapConfig.Create("synap://127.0.0.1:15501"));

// Queue round-trip
await client.Queue.CreateQueueAsync("tasks", 1000, 60);
var id = await client.Queue.PublishAsync("tasks", new { job = "resize" }, 5);
var msg = await client.Queue.ConsumeAsync("tasks", "worker-1");
await client.Queue.AckAsync("tasks", msg!.Id);

// Stream publish + read
await client.Stream.CreateRoomAsync("events");
await client.Stream.PublishAsync("events", "user.created", new { id = "u1" });
var events = await client.Stream.ReadAsync("events", 0);

// Reactive pub/sub (server-push via IAsyncEnumerable on synap://)
await foreach (var push in client.PubSub.ObserveAsync(["news.*"], cancellationToken))
{
    Console.WriteLine($"got: {push["topic"]}");
}

API Reference

Configuration

using Synap.SDK;

var config = SynapConfig.Create("http://localhost:15500")
    .WithTimeout(60)
    .WithAuthToken("your-token")
    .WithMaxRetries(5);

var client = new SynapClient(config);

Key-Value Store

// Set value with TTL
await client.KV.SetAsync("session:abc", sessionData, ttl: 3600);

// Get value (generic)
var data = await client.KV.GetAsync<SessionData>("session:abc");

// Atomic operations
var newValue = await client.KV.IncrAsync("counter", delta: 1);
var exists = await client.KV.ExistsAsync("session:abc");

// Scan keys
var keys = await client.KV.ScanAsync("user:*", limit: 100);

// Get stats
var stats = await client.KV.StatsAsync();

KV Watch (Reactive)

Observe a key — or a wildcard pattern — and receive its new value on every change, without polling. Requires the synap:// transport; cancelling the enumeration issues KV.UNWATCH:

using var cts = new CancellationTokenSource();

// Watch one key, or a whole prefix
await foreach (var e in client.KV.WatchAsync("user:*", cancellationToken: cts.Token))
{
    // e: WatchEvent { Key, Event, Version, Value, Truncated }
    Console.WriteLine($"{e.Event} {e.Key} v{e.Version} = {e.Value}");
}

// Notify-only mode: change signals without value bandwidth (re-GET on demand)
await foreach (var e in client.KV.WatchAsync("hot:key", WatchMode.Notify, cts.Token))
{
    var current = await client.KV.GetAsync<string>(e.Key);
}

Delivery is best-effort, latest-value; Version resets when the key is deleted, expires or is evicted — version 1 marks a new incarnation.

Message Queues

// Create queue
await client.Queue.CreateQueueAsync("tasks", maxSize: 10000, messageTtl: 3600);

// Publish message with priority
var messageId = await client.Queue.PublishAsync(
    "tasks",
    new { action = "encode", file = "video.mp4" },
    priority: 9,
    maxRetries: 3
);

// Consume and process
var message = await client.Queue.ConsumeAsync("tasks", "worker-1");
if (message is not null)
{
    try
    {
        // Process message
        await ProcessAsync(message.Payload);
        await client.Queue.AckAsync("tasks", message.Id);
    }
    catch
    {
        await client.Queue.NackAsync("tasks", message.Id); // Requeue
    }
}

// Get queue stats
var stats = await client.Queue.StatsAsync("tasks");
var queues = await client.Queue.ListAsync();

Event Streams

// Create stream room
await client.Stream.CreateRoomAsync("events");

// Publish event
var offset = await client.Stream.PublishAsync("events", "user.created", new
{
    userId = "123",
    name = "Alice"
});

// Read events
var events = await client.Stream.ReadAsync("events", offset: 0, limit: 100);
foreach (var evt in events)
{
    Console.WriteLine($"Event: {evt.Event} at offset {evt.Offset}");
}

// Get stream stats
var stats = await client.Stream.StatsAsync("events");
var rooms = await client.Stream.ListRoomsAsync();

Pub/Sub

// Subscribe to topics (supports wildcards)
await client.PubSub.SubscribeTopicsAsync("subscriber-1", new List<string>
{
    "user.created",
    "notifications.*",
    "events.#"
});

// Publish message
var delivered = await client.PubSub.PublishAsync("notifications.email", new
{
    to = "user@example.com",
    subject = "Welcome!"
});

Console.WriteLine($"Delivered to {delivered} subscribers");

// Unsubscribe
await client.PubSub.UnsubscribeTopicsAsync("subscriber-1", new List<string> { "notifications.*" });

// Get stats
var stats = await client.PubSub.StatsAsync();

Async Patterns

All operations support CancellationToken:

var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(5));

try
{
    var value = await client.KV.GetAsync<string>("key", cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Operation was cancelled");
}

Error Handling

using Synap.SDK.Exceptions;

try
{
    await client.KV.SetAsync("key", "value");
}
catch (SynapException ex)
{
    Console.WriteLine($"Synap error: {ex.Message}");
}

Custom HttpClient

You can provide your own HttpClient for advanced scenarios:

var httpClient = new HttpClient
{
    Timeout = TimeSpan.FromSeconds(120)
};

var config = SynapConfig.Create("http://localhost:15500");
var client = new SynapClient(config, httpClient);

License

Apache License 2.0 - See LICENSE for details.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.3.0 92 7/21/2026
1.2.3 97 7/20/2026
1.2.0 92 7/19/2026
1.0.0 94 7/14/2026
0.11.1 117 4/11/2026